{"id":7018,"date":"2019-07-11T20:26:27","date_gmt":"2019-07-11T20:26:27","guid":{"rendered":"https:\/\/ormuco.com\/?p=7018"},"modified":"2019-11-12T15:54:46","modified_gmt":"2019-11-12T15:54:46","slug":"blog-deploying-qinling-production","status":"publish","type":"post","link":"https:\/\/ormuco.com\/fr\/blog\/deploying-qinling-production","title":{"rendered":"A Quickstart Guide to Deploying Qinling in Production"},"content":{"rendered":"<p>Qinling is an OpenStack project to provide Function-as-a-Service. This project aims to provide a platform to support serverless functions (like AWS Lambda). Qinling supports different container orchestration platforms (Kubernetes\/Swarm, etc\u2026) and different function package storage backends (local\/Swift\/S3) by nature using plugin mechanism.<\/p>\n<p>Basically, it allows you to trigger a function only when you need it, helping you to consume only the CPU and memory time that you really need without requiring you to configure any servers. In the end, this makes for a lighter billing, making everyone happy. (There\u2019s a lot\u00a0<a href=\"https:\/\/medium.com\/@n.neerja28\/qinling-in-a-nutshell-6d9cf3537346\">more about Qinling<\/a> online if you want to take a deeper dive.)<\/p>\n<h2>Deploying Qinling in production<\/h2>\n<p>Our platforms are deployed and maintained by\u00a0<a href=\"https:\/\/wiki.openstack.org\/wiki\/Kolla\">Kolla<\/a>, an OpenStack project to deploy OpenStack within Docker and configured by\u00a0<a href=\"https:\/\/www.ansible.com\/integrations\/cloud\/openstack\">Ansible<\/a>. The first thing I checked was to see if Qinling integrated with Kolla, alas\u2026no.<\/p>\n<p>When you have to manage production you don\u2019t want or like to deal with custom setups that are impossible to maintain or to upgrade (that little voice in your head knows what I mean), so I started working integrating Qinling in Kolla, namely the\u00a0<a href=\"https:\/\/review.opendev.org\/#\/c\/659422\/\">Docker<\/a>\u00a0and\u00a0<a href=\"https:\/\/review.opendev.org\/#\/c\/660789\/\">Ansible<\/a> parts.<\/p>\n<p>The qinling_api and qinling_engine containers are now up and running, configured to communicate with RabbitMQ, MySQL\/Galera, memcached, Keystone and etcd. The final important step is to authenticate qinling-engine to the Kubernetes cluster \u2014 I must admit this was the most complex to set up and that the documentation is a bit confusing.<\/p>\n<h2>Qinling and Magnum, for the win!<\/h2>\n<p>Our Kubernetes cluster has been provisioned by OpenStack Magnum, an OpenStack project used to deploy container orchestration engines (COE) such as Docker Swarm, Mesos and Kubernetes.<\/p>\n<p>Basically, the communication between Qinling and Kubernetes is done by SSL certificates (the same ones used with kubectl), qinling-engine needs to be aware of the CA, the certificate and the key and the Kubernetes API endpoint.<\/p>\n<p>Magnum provides a CLI which allows easily to retrieve the certificates, just make sure that you have python-magnumclient installed.<\/p>\n<pre><code class=\"hljs ruby\"><span class=\"hljs-comment\"># Get Magnum cluster UUID<\/span>\r\n$ openstack coe cluster list -f value -c uuid -c name\r\n<span class=\"hljs-number\">687<\/span>f7476\u2013<span class=\"hljs-number\">5604<\/span>\u2013<span class=\"hljs-number\">4<\/span>b44\u2013<span class=\"hljs-number\">8<\/span>b09-b7a4f3fdbd64 goldyfruit-k8s-qinling<\/code><\/pre>\n<pre><code class=\"hljs ruby\"><span class=\"hljs-comment\"># Retrieve Kubernetes certificates<\/span>\r\n$ mkdir -p ~<span class=\"hljs-regexp\">\/k8s_configs\/goldyfruit<\/span>-k8s-qinling\r\n$ cd ~<span class=\"hljs-regexp\">\/k8s_configs\/goldyfruit<\/span>-k8s-qinling\r\n$ openstack coe cluster config --dir . <span class=\"hljs-number\">687<\/span>f7476-<span class=\"hljs-number\">5604<\/span>-<span class=\"hljs-number\">4<\/span>b44-<span class=\"hljs-number\">8<\/span>b09-b7a4f3fdbd64 --output-certs<\/code><\/pre>\n<pre><code class=\"hljs perl\"><span class=\"hljs-comment\"># Get the Kubernetes API address<\/span>\r\n$ <span class=\"hljs-keyword\">grep<\/span> server config | awk -F<span class=\"hljs-string\">\"server:\"<\/span> <span class=\"hljs-string\">'{ print $2 }'<\/span><\/code><\/pre>\n<p>Four files should have been generated in ~\/k8s_configs\/goldyfruit-k8s-qinling directory:<\/p>\n<pre><code class=\"hljs css\"><span class=\"hljs-selector-tag\">ca<\/span><span class=\"hljs-selector-class\">.pem<\/span>\u200a\u2014\u200a<span class=\"hljs-selector-tag\">CA<\/span>\u200a\u2014\u200a<span class=\"hljs-selector-tag\">ssl_ca_cert<\/span> (<span class=\"hljs-selector-tag\">Qinling<\/span> <span class=\"hljs-selector-tag\">option<\/span>)\r\n<span class=\"hljs-selector-tag\">cert<\/span><span class=\"hljs-selector-class\">.pem<\/span>\u200a\u2014\u200a<span class=\"hljs-selector-tag\">Certificate<\/span>\u200a\u2014\u200a<span class=\"hljs-selector-tag\">cert_file<\/span> (<span class=\"hljs-selector-tag\">Qinling<\/span> <span class=\"hljs-selector-tag\">option<\/span>)\r\n<span class=\"hljs-selector-tag\">key<\/span><span class=\"hljs-selector-class\">.pem<\/span>\u200a\u2014\u200a<span class=\"hljs-selector-tag\">Key<\/span>\u200a\u2014\u200a<span class=\"hljs-selector-tag\">key_file<\/span> (<span class=\"hljs-selector-tag\">Qinling<\/span> <span class=\"hljs-selector-tag\">option<\/span>)\r\n<span class=\"hljs-selector-tag\">config<\/span>\u2014 <span class=\"hljs-selector-tag\">Kubernetes<\/span> <span class=\"hljs-selector-tag\">configuration<\/span><\/code><\/pre>\n<p>Only ca.pem, cert.pem and key.pem will be useful in our case (config file will only be used to get the Kubernetes API), which from Qinling documentation will become these options:<\/p>\n<pre><code class=\"hljs ini\"><span class=\"hljs-section\">[kubernetes]<\/span>\r\n<span class=\"hljs-attr\">kube_host<\/span> = https:\/\/<span class=\"hljs-number\">192.168<\/span>.<span class=\"hljs-number\">1.168<\/span>:<span class=\"hljs-number\">6443<\/span>\r\n<span class=\"hljs-attr\">ssl_ca_cert<\/span> = \/etc\/qinling\/pki\/kubernetes\/ca.crt\r\n<span class=\"hljs-attr\">cert_file<\/span> = \/etc\/qinling\/pki\/kubernetes\/qinling.crt\r\n<span class=\"hljs-attr\">key_file<\/span> = \/etc\/qinling\/pki\/kubernetes\/qinling.key<\/code><\/pre>\n<p>At this point if qinling-engine has restarted, then you should see a network policy created on the Kubernetes cluster under the qinling namespace (yes, you should see that too).<\/p>\n<p>The network policy mentioned above could block the incoming traffic to the pods inside the qinling namespace which result in a timeout from qinling-engine. A\u00a0<a href=\"https:\/\/storyboard.openstack.org\/#!\/story\/2005710\">bug has been opened<\/a>\u00a0about this issue and it should be solved soon, so right now the \u201cbest\u201d thing to do is to remove this policy (keep in mind that every time than qinling-engine will be restarted the policy will be re-created).<\/p>\n<pre><code class=\"hljs sql\">$ kubectl <span class=\"hljs-keyword\">delete<\/span> netpol <span class=\"hljs-keyword\">allow<\/span>-qinling-<span class=\"hljs-keyword\">engine<\/span>-<span class=\"hljs-keyword\">only<\/span> -n qinling<\/code><\/pre>\n<p>Just a quick word about the network policy created by Qinling. It has the objective to restrict the pod access to a trusted CIDR list (192.168.1.0\/24, 10.0.0.53\/32, etc\u2026) preventing connections from unknown sources.<\/p>\n<p>One common issue is to forget to open the Qinling API port (7070), this will prevent the Kubernetes cluster to download the function code\/package (it\u2019s time to be nice with your dear network friend ^^).<\/p>\n<h2>Runtime, it\u2019s time to run!<\/h2>\n<p>One of Qinling pitfalls is the \u201clack\u201d of runtime, preventing Qinling to be widely adopted, the reason why there are not that much is because of security reasons (completely understandable).<\/p>\n<p>Actually, in the production environment (especially in the public cloud), it\u2019s recommended that cloud providers supply their own runtime implementation for security reasons. Knowing how the runtime is implemented gives the malicious user the chance to attack the cloud environment.<\/p>\n<p>So far, \u201conly\u201d Python 2.7, Python 3 and Node.JS runtimes are available, it\u2019s a good start but it would be nice to have it for Golang and PHP too (just saying, not asking).<\/p>\n<h2>Conclusion<\/h2>\n<p>My journey has just begun and I think Qinling has a huge potential, which is why I was a bit surprised to see the project isn\u2019t popular as it could be.<\/p>\n<p>Having it in Kolla, improving the documentation for integration with Magnum, Microk8s, etc\u2026 and providing more runtimes would help the project to gain the popularity it deserves.<\/p>\n<p>Thanks to\u00a0<a href=\"https:\/\/www.linkedin.com\/in\/lingxian-kong-a1b23610a\">Lingxian Kong<\/a>\u00a0and the community for making this project happen!<\/p>\n<p><em>This post has appeared on <a href=\"https:\/\/superuser.openstack.org\/articles\/how-to-deploy-qinling-in-production\/\">Superuser<\/a> and <a href=\"https:\/\/medium.com\/@goldyfruit\/qinling-lets-the-journey-begin-c26ddc252b8a\">Medium<\/a>.<\/em><\/p>\n<p><a href=\"https:\/\/ormuco.com\/fr\/webcast\/openstack-summit-2018\/\"><img loading=\"lazy\" class=\"size-full wp-image-7034 aligncenter\" src=\"https:\/\/ormuco.com\/wp-content\/uploads\/2019\/07\/Qinling-CTA-1-1.png\" alt=\"OpenStack Summit\" width=\"336\" height=\"280\" srcset=\"https:\/\/ormuco.com\/wp-content\/uploads\/2019\/07\/Qinling-CTA-1-1.png 336w, https:\/\/ormuco.com\/wp-content\/uploads\/2019\/07\/Qinling-CTA-1-1-300x250.png 300w, https:\/\/ormuco.com\/wp-content\/uploads\/2019\/07\/Qinling-CTA-1-1-270x225.png 270w\" sizes=\"(max-width: 336px) 100vw, 336px\" \/><\/a><\/p>","protected":false},"excerpt":{"rendered":"<p>Qinling is an OpenStack project to provide Function-as-a-Service. This project aims to provide a platform to support serverless functions (like AWS Lambda). Qinling supports different container orchestration platforms (Kubernetes\/Swarm, etc\u2026) and different function package storage backends (local\/Swift\/S3) by nature using plugin mechanism. Basically, it allows you to trigger a function only when you need it, [&hellip;]<\/p>","protected":false},"author":8,"featured_media":7027,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"spay_email":""},"categories":[74],"tags":[],"jetpack_featured_media_url":"https:\/\/ormuco.com\/wp-content\/uploads\/2019\/07\/Qinling-Header.png","yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v15.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>A Quickstart Guide to Deploying Qinling in Production - Ormuco<\/title>\n<meta name=\"description\" content=\"Learn how to deploy Qinling using Kolla and Kolla Ansible, and use Kubernetes deployed with OpenStack Magnum as Qinling backend.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ormuco.com\/fr\/blog\/deploying-qinling-production\/\" \/>\n<meta property=\"og:locale\" content=\"fr_CA\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"A Quickstart Guide to Deploying Qinling in Production - Ormuco\" \/>\n<meta property=\"og:description\" content=\"Learn how to deploy Qinling using Kolla and Kolla Ansible, and use Kubernetes deployed with OpenStack Magnum as Qinling backend.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ormuco.com\/fr\/blog\/deploying-qinling-production\/\" \/>\n<meta property=\"og:site_name\" content=\"Ormuco\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Ormuco\/\" \/>\n<meta property=\"article:published_time\" content=\"2019-07-11T20:26:27+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2019-11-12T15:54:46+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/ormuco.com\/wp-content\/uploads\/2019\/07\/Qinling-Header.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"628\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/goldyfruit\" \/>\n<meta name=\"twitter:site\" content=\"@Ormuco_Inc\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\">\n\t<meta name=\"twitter:data1\" content=\"3 minutes\">\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https:\/\/ormuco.com\/#organization\",\"name\":\"Ormuco Inc\",\"url\":\"https:\/\/ormuco.com\/\",\"sameAs\":[\"https:\/\/www.facebook.com\/Ormuco\/\",\"https:\/\/www.linkedin.com\/company\/ormuco-inc-\/\",\"https:\/\/www.youtube.com\/channel\/UCbzzf28bWMg0zhOrq0fI_sQ\",\"https:\/\/twitter.com\/Ormuco_Inc\"],\"logo\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/ormuco.com\/#logo\",\"inLanguage\":\"fr-CA\",\"url\":\"https:\/\/ormuco.com\/wp-content\/uploads\/2018\/07\/Ormuco_logo.png\",\"width\":360,\"height\":89,\"caption\":\"Ormuco Inc\"},\"image\":{\"@id\":\"https:\/\/ormuco.com\/#logo\"}},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/ormuco.com\/#website\",\"url\":\"https:\/\/ormuco.com\/\",\"name\":\"Ormuco\",\"description\":\"Next Generation Mobile Computing\",\"publisher\":{\"@id\":\"https:\/\/ormuco.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/ormuco.com\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"fr-CA\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/ormuco.com\/blog\/deploying-qinling-production\/#primaryimage\",\"inLanguage\":\"fr-CA\",\"url\":\"https:\/\/ormuco.com\/wp-content\/uploads\/2019\/07\/Qinling-Header.png\",\"width\":1200,\"height\":628,\"caption\":\"Qinling\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/ormuco.com\/blog\/deploying-qinling-production\/#webpage\",\"url\":\"https:\/\/ormuco.com\/blog\/deploying-qinling-production\/\",\"name\":\"A Quickstart Guide to Deploying Qinling in Production - Ormuco\",\"isPartOf\":{\"@id\":\"https:\/\/ormuco.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/ormuco.com\/blog\/deploying-qinling-production\/#primaryimage\"},\"datePublished\":\"2019-07-11T20:26:27+00:00\",\"dateModified\":\"2019-11-12T15:54:46+00:00\",\"description\":\"Learn how to deploy Qinling using Kolla and Kolla Ansible, and use Kubernetes deployed with OpenStack Magnum as Qinling backend.\",\"inLanguage\":\"fr-CA\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/ormuco.com\/blog\/deploying-qinling-production\/\"]}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/ormuco.com\/blog\/deploying-qinling-production\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/ormuco.com\/blog\/deploying-qinling-production\/#webpage\"},\"author\":{\"@id\":\"https:\/\/ormuco.com\/#\/schema\/person\/8930db9427f4e9749532f30d2263bc31\"},\"headline\":\"A Quickstart Guide to Deploying Qinling in Production\",\"datePublished\":\"2019-07-11T20:26:27+00:00\",\"dateModified\":\"2019-11-12T15:54:46+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/ormuco.com\/blog\/deploying-qinling-production\/#webpage\"},\"publisher\":{\"@id\":\"https:\/\/ormuco.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/ormuco.com\/blog\/deploying-qinling-production\/#primaryimage\"},\"articleSection\":\"Developers Corner\",\"inLanguage\":\"fr-CA\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/ormuco.com\/#\/schema\/person\/8930db9427f4e9749532f30d2263bc31\",\"name\":\"Ga\\u00ebtan Trellu\",\"description\":\"Ga\\u00ebtan manages the TechOps team to implement and stabilize new features on the Ormuco Infrastructure-as-a-Service platform. Ga\\u00ebtan has previously worked as a DevOps Engineer and as the CloudOps Lead at Ormuco. He is self-taught in IT, with particular expertise in the Unix and Linux ecosystems.\",\"sameAs\":[\"https:\/\/www.linkedin.com\/in\/gaetantrellu\/\",\"https:\/\/twitter.com\/https:\/\/twitter.com\/goldyfruit\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","jetpack_shortlink":"https:\/\/wp.me\/pa8ID1-1Pc","_links":{"self":[{"href":"https:\/\/ormuco.com\/fr\/wp-json\/wp\/v2\/posts\/7018"}],"collection":[{"href":"https:\/\/ormuco.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ormuco.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ormuco.com\/fr\/wp-json\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/ormuco.com\/fr\/wp-json\/wp\/v2\/comments?post=7018"}],"version-history":[{"count":9,"href":"https:\/\/ormuco.com\/fr\/wp-json\/wp\/v2\/posts\/7018\/revisions"}],"predecessor-version":[{"id":7952,"href":"https:\/\/ormuco.com\/fr\/wp-json\/wp\/v2\/posts\/7018\/revisions\/7952"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ormuco.com\/fr\/wp-json\/wp\/v2\/media\/7027"}],"wp:attachment":[{"href":"https:\/\/ormuco.com\/fr\/wp-json\/wp\/v2\/media?parent=7018"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ormuco.com\/fr\/wp-json\/wp\/v2\/categories?post=7018"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ormuco.com\/fr\/wp-json\/wp\/v2\/tags?post=7018"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}