Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Taipei.rb 像 Capistrano 一樣用 Kubernetes 部署 Rails

888339de9e7a88688b6acb30d33e66cd?s=47 蒼時弦や
February 14, 2018

Taipei.rb 像 Capistrano 一樣用 Kubernetes 部署 Rails

888339de9e7a88688b6acb30d33e66cd?s=128

蒼時弦や

February 14, 2018
Tweet

Transcript

  1. 像 Capistrano 一樣 用 Kubernetes 部署 Rails

  2. 襟 儘 䓛⛳ @elct9620 WEB DEVELOPER GAME DEVELOPER

  3. None
  4. Why Kubernetes?

  5. 找不到 Clone 機器的選項 (/‵Д′)/~ ╧╧ Google Cloud Platform

  6. Google Kubernetes Engine

  7. Automated container deployment, scaling, and management Container Orchestration

  8. 想要用 Kuberneters 要先會做 (Docker) Image Container

  9. None
  10. 把安裝環境的指令都寫進去就對了⋯⋯ Dockerfile

  11. FROM FROM ruby:2.4.3

  12. ENV ENV LC_ALL C.UTF-8 ENV TZ Asia/Taipei ENV APP_HOME /usr/src/app

    ENV RAILS_ENV production
  13. RUN RUN mkdir -p $APP_HOME

  14. ADD ADD Gemfile $APP_HOME/Gemfile ADD Gemfile.lock $APP_HOME/Gemfile.lock

  15. RUN AGAIN… RUN cd $APP_HOME && bundle install --without development

    test --deployment
  16. ADD AGAIN… ADD . $APP_HOME

  17. Before Start Application RUN rake assets:precompile

  18. EXPOSE / CMD WORKDIR $APP_HOME EXPOSE 3000 CMD rails server

  19. 簡單的 Dockerfile 當寫部署伺服器的 Shell Script 就好 Shell Script

  20. 這會大大影響封裝的時間,穩定後可以把 RUN 合併處理 但是要注意順序

  21. 封裝 Image 用 -t 給名字 docker build -t example/app .

  22. docker tag example/app example/app:0.1.0 用 tag 上版號

  23. 其實就是 Google Bucket Google Container Registry

  24. 要上傳到 Google Container Registry 就要明確指定伺服器和專案 gcr.io/example-1234/app:0.1.0

  25. 因為 GCR 需要登入驗證,所以可以透過 gcloud 指令自動填入認證 gcloud docker -- push [IMAGE_NAME]

  26. 回到正題⋯⋯ Kubernetes

  27. 因為會自動分配資源,所以硬碟也會被隨機分配需要另外設定 今天只討論 Stateless 的情況

  28. 用來定義啟動一個環境的時候需要做什麼,所以會有一個 template 設定 Deployment 設定

  29. Deployment 建出來的是一個 Pod 單位,可能是多個容器組成 Pod 的觀念

  30. Deployment 建出來的 Pod 是無法直接被他人使用的,需要定義成服務 Service 設定

  31. 看幾張圖當範例 Deployment + Service = ?

  32. Service Pod Pod Pod Pod rails.svc.cluster.local

  33. Service rails.svc.cluster.local Volume Sidekiq Rails 5 Volume Sidekiq Rails 4

  34. Service rails.svc.cluster.local Volume Sidekiq Rails 5 Volume Sidekiq Rails 4

    Selector: #app #app #v2 #app #v1
  35. 透過 Label / Selector 機制選擇 Service 對應的不一定是相同的 Deployment

  36. 需要對外暴露才行 還是只能在 Kubernetes 內部取用

  37. 目前 AWS/GCP 有支援,其他需要透過 Nginx 模擬 LoadBalancer

  38. GKE 連不上 (/‵Д′)/~ ╧╧ CloudSQL

  39. 設定檔很複雜,所以我們用 Rake Task 生成 所以怎麼用?

  40. wc -l vendor/template/* 33 vendor/template/cronjob.yaml 70 vendor/template/app.yaml 62 vendor/template/app_admin.yaml 49

    vendor/template/elasticsearch.yaml 41 vendor/template/memcached.yaml 59 vendor/template/mysql.yaml 49 vendor/template/redis.yaml 363 total
  41. 先要有 Kuberentes 的 CLI 工具 gcloud components install kubectl

  42. 用前面在本機封裝的 Dockerfile 生成 example/rails Image 來啟動一個 Rails 專案

  43. apiVersion: extensions/v1beta1 kind: Deployment metadata: name: rails labels: app: web

    spec: replicas: 1 template: metadata: labels: app: web spec: containers: - name: rails image: example/rails ports: - containerPort: 3000
  44. apiVersion: extensions/v1beta1 kind: Deployment metadata: name: rails labels: app: web

    spec: replicas: 1 template: metadata: labels: app: web spec: containers: - name: rails image: example/rails ports: - containerPort: 3000
  45. apiVersion: extensions/v1beta1 kind: Deployment metadata: name: rails labels: app: web

    spec: replicas: 1 template: metadata: labels: app: web spec: containers: - name: rails image: example/rails ports: - containerPort: 3000
  46. apiVersion: extensions/v1beta1 kind: Deployment metadata: name: rails labels: app: web

    spec: replicas: 1 template: metadata: labels: app: web spec: containers: - name: rails image: example/rails ports: - containerPort: 3000
  47. apiVersion: extensions/v1beta1 kind: Deployment metadata: name: rails labels: app: web

    spec: replicas: 1 template: metadata: labels: app: web spec: containers: - name: rails image: example/rails ports: - containerPort: 3000
  48. Service web.svc.cluster.local Rails 5 PostgreSQL Selector: #app #app #db Service

    db.svc.cluster.local Selector: #db
  49. apiVersion: v1 kind: Service metadata: name: web labels: app: web

    spec: type: LoadBalancer loadBalancerIP: 172.31.1.10 ports: - port: 80 targetPort: 3000 selector: app: web
  50. apiVersion: v1 kind: Service metadata: name: web labels: app: web

    spec: type: LoadBalancer loadBalancerIP: 172.31.1.10 ports: - port: 80 targetPort: 3000 selector: app: web
  51. apiVersion: v1 kind: Service metadata: name: web labels: app: web

    spec: type: NodePort ports: - port: 80 targetPort: 3000 selector: app: web
  52. 寫設定檔是為了可以用 -f 直接操作 kubectl apply -f deploy.yaml

  53. 之後大概寫個 Rake Task 就可以收工 rake k8s:staging:deploy

  54. 所以要寫 ERB Template 去更新設定檔 不用改 Image 的版本嗎?

  55. (/‵Д′)/~ ╧╧

  56. None
  57. gem install kubec

  58. None
  59. 寫起來比較親切 用 Ruby 的方法解決

  60. 跟 cap install 一樣 kubec install

  61. 跟 config/deploy.rb 一樣 vim config/kubec.rb

  62. deployment :web do label :app, :web template do label :app,

    :web container :web do image fetch(:image, 'elct9620/example') port 3000 env 'DATABASE_URL', 'postgres://...' end end end service :web do select :app, :web node_port port 80, 3000 end
  63. 跟 cap staging deploy 一樣 kubec staging deploy

  64. 總覽 Kubernetes 部署的狀況 kubec staging status

  65. 如果有設定檔需要上傳呢? cap staging config:push

  66. config :example do file './config/application.yaml' end deployment :web do label

    :app, :ruby template do label :app, :ruby container :web do # ... config_file 'application.yaml', path: '/usr/src/app/config', from: :config end volume :config do config :configs, 'application.yaml' => 'application.yaml' end end end
  67. 利用 Kubernetes 的 ConfigMap/Secret 掛載到 Container 中 kubec staging config:push

  68. 目前還處於早期開發階段,希望大家協助後續的開發 https://github.com/5xRuby/kubec

  69. 自動化? CI/CD

  70. 和傳統的流程沒什麼差異 CI

  71. 現階段用現成的服務比較簡單 CD

  72. Build Docker Image Push to Registry Apply Config

  73. Jenkins / Gitlab CI 基本上都能做到 Build Docker Image

  74. 主要難點在於傳到 GCP/AWS 的認證保存 Push to Registry

  75. 除了認證保管之外還多了 kubectl 環境安裝的問題 Apply Config

  76. None
  77. 想自己弄就要再多花時間 Build/Push Image 都支援

  78. 有 Set Image 的選項,不過設定多就不方便 Apply Config

  79. 直接出設定檔,然後用 apply 的方式更新 kubec staging deploy:dump > config.yaml

  80. 如果是大量使用 Container 會很方便,不過學習曲線偏高 Production 環境 Cluster 一般是三台開始,用量不大也暫時不需要考慮 結論

  81. None