Google Cloud Kubernetes EngineにRuby on Railsをデプロイする際の注意事項



Kubernetes EngineでGoogle Cloudを2か月間使用しています。 実際、すべてを頭に入れるのに1か月はかかりませんでしたが、いくつかのトラブルに対処するには同じくらいかかりました。







TL; DR:Googleはかなり良い仕事をしているので、AWSはリラックスしていません。 AWSをよく知っているなら、Google Cloudをテストすることをお勧めします。 私は筋肉の記憶のためにAWSに慣れているかもしれませんが、Google CloudとKubernetesを研究しており、ほとんどのシナリオで自信を持っています。







私は専門家ではありませんので、ある程度懐疑的に私の言葉を受け入れてください。 Google CloudとKubernetesは、私が本当に話したいトピックの1つですが、常に適切な言葉を見つけることができるわけではありません。提案されたソリューションについて正しいアイデアを得ることができれば幸いです。







この記事の目的は、将来の使用のためにいくつかの断片と思考を保存することです。 したがって、これは段階的なガイドではないことに注意してください。 最初はガイドを書くつもりでしたが、今度は本全体を書くようなものであることに気づきました。







Google CloudやKubernetesなどで成功するには、十分な経験が必要です。 Linux From Scratchをインストールしたことがない場合、サーバーの最適化を実行したことがない場合、Ironサーバーコンポーネントが気に入らない場合は、実際の運用展開を実行しないでください。 最も安全な賭けはまだHerokuにあります。







あなたは(私の以前のブログのように)いじくり回すのが好きな人でなければなりません。







私はすべてを知りませんが、十分に知っています。 まず、必要なものを理解する必要がありました。 最初のYAMLファイルを作成する前に、ニーズを述べることが重要です。 計画は非常に重要です。







必要なものは次のとおりです。









シンプルなデモWebアプリケーションは簡単にデプロイできます。 しかし、私はデモを望んでいませんでした、私は長期的に生産のためのソリューションを望んでいました。







いくつかの初心者の問題:









もう一度思い出させてください。これはステップバイステップのガイドではありません 。 いくつかのステップに注釈を付けます。







スケーラブルなWeb層(Webアプリ自体)



最初に必要なのは、完全な12因子アプリです。







Ruby on Rails、Django、Laravel、Node.js(とにかく)であっても、これは共有アクセスを持たず、ローカルファイルシステムへの書き込みに依存しないアプリケーションでなければなりません。 インスタンスを個別に簡単に無効にして実行できるアプリケーション。 ローカルメモリまたはローカルファイルにセッションが存在しないようにする必要があります(セッションの近接を避けることをお勧めします)。 ローカルファイルシステムへのファイルアップロードはありません(必要に応じて、外部永続ストレージをマウントする必要があります)。常に、マネージドストレージサービスにバイナリストリームを送信することをお勧めします。

フィンガープリント資産を介してキャッシュを出力する適切なパイプラインが必要です(好むと好まざるとにかかわらず、RailsはAsset Pipelineですぐに使える最高のソリューションを提供しています)。

アプリケーションをインストルメントし、 New Relic RPMRollbarを追加します。

2018年、SQLインジェクション(または他の入力)を使用して独自のコードを展開したくない、コードの周りで制御されていない評価、CSRFまたはXSSなどの場所がありません。 CIコンベヤー。 私は待つことができます...

これはチュートリアルではないため、Google Cloudに登録して、プロジェクト、地域、ゾーンを設定できると想定しています。

Google Cloudの主要な構造を理解するには少し時間がかかりました。









 gcloud container clusters create my-web-production \ --enable-cloud-logging \ --enable-cloud-monitoring \ --machine-type n1-standard-4 \ --enable-autoupgrade \ --enable-autoscaling --max-nodes=5 --min-nodes=2 \ --num-nodes 2
      
      





前述のように、クラスターはマシンタイプ n1-standard-4



default-pool



を作成しdefault-pool



。 アプリケーションに必要なCPU / RAMの組み合わせを選択します。 選択したタイプには、4つのvCPUと15 GBのRAMがあります。







デフォルトでは、3つのノードから開始するため、最初に2つを選択しましたが、自動的に5にスケーリングされました(必要に応じて後で更新できますが、最初の成長の余地があることを確認してください)。 たとえば、Sidekiqワーカーが集中的なバックグラウンド処理を実行するために、サイズの異なるノードのインスタンスにプールを追加し続けることができます。 次に、インスタンスのセットに対して異なるマシンタイプのノードの別個のプールを作成します。次に例を示します。







 gcloud container node-pools create large-pool \ --cluster=my-web-production \ --node-labels=pool=large \ --machine-type=n1-highcpu-8 \ --num-nodes 1
      
      





このもう1つのプールは、 n1-highcpu-8



タイプの1つのノードを制御します。これには、7.2 GBのRAMを備えた8つのvCPUがあります。 より多くのプロセッサ、より少ないメモリ。 highmem



カテゴリがあり、これはCPUよりも小さく、より多くのメモリがあります。 繰り返しますが、あなたはあなたが望むものを知る必要があります。







ここで重要な点は、-- --node-labels



です。ホストプール間(この場合、デフォルトプールとラージプール間)を選択するために展開をマップする方法です。







クラスターを作成したら、次のコマンドを発行して資格情報を取得する必要があります。







gcloud container clusters get-credentials my-web-production









このコマンドはkubectl



定義しkubectl



。 複数のクラスターがある場合( my-web-production





およびmy-web-staging



)、正しいクラスターのget-credentials



注意する必要があります。そうしないと、実稼働クラスターで中間デプロイメントを実行できます。







これは混乱を招くため、ZSH PROMPTを変更して、直面しているクラスターを常に表示するようにしました。 私はzsh-kubectl-promptから適応しました:













大規模なアプリケーションには多くのクラスターがあるため、このプロンプトをシェルに追加することを強くお勧めします。







ノードインスタンスのポッドにアプリケーションをどのようにデプロイしますか?







Dockerイメージを作成するには、アプリケーションプロジェクトリポジトリにDockerファイルが必要です。 これは、Ruby on Railsアプリケーションの一例です。







 FROM ruby:2.4.3 ENV RAILS_ENV production ENV SECRET_KEY_BASE xpto RUN curl -sL https://deb.nodesource.com/setup_8.x | bash - RUN apt-get update && apt-get install -y nodejs postgresql-client cron htop vim ADD Gemfile* /app/ WORKDIR /app RUN gem update bundler --pre RUN bundle install --without development test RUN npm install ADD . /app RUN cp config/database.yml.prod.example config/database.yml && cp config/application.yml.example config/application.yml RUN RAILS_GROUPS=assets bundle exec rake assets:precompile
      
      





Google Cloud Web Consoleには、プライベートDockerレジストリである「コンテナレジストリ」があります。







次のように、ローカル構成にリモートURLを追加します。







git remote add gcloud https://source.developers.google.com/p/my-project/r/my-app









git push gcloud master



ができるgit push gcloud master



。 画像にタグを付けるトリガーを追加することをお勧めします 。 2つのトリガーを追加します。1つはlatest



マークを付け、もう1つはランダムなバージョン番号でマークを付けます。 後で必要になります。







git構成でレジストリリポジトリをリモートとして追加した後( git remote add



)、それをクリックします。 トリガーを使用して構成した適切なタグでDockerイメージの作成を開始する必要があります。







データベース接続が利用できないため、Ruby on Railsアプリケーションがデータベース接続を必要とする初期化子に何もないことを確認してください。 assets:precompile



-タスクが誤ってモデルを呼び出す初期化子をロードし、これがActiveRecord :: Base



トリガーを呼び出して接続を試行するという事実により、Dockerビルドが失敗するとスタックする可能性があります。







DockerfileのRubyのバージョンがGemfileのバージョンと一致していることを確認してください。一致していない場合も失敗します。







奇妙なconfig/application.yml



気づきました。 これはfigaroからです。 システム内のENV変数の構成を簡素化することをお勧めします。 私はRailsの秘密が好きではありません。HerokuがENV varを遍在化した後の展開システムにはあまり馴染みがありません。 ENV変数に固執します。 Kubernetesはこれに感謝します。







これで、Kubernetesおよびyamlデプロイメントファイルの環境変数をオーバーライドできます。 今こそ、例を設定するときです。 deploy / web.yml



またはそれがあなたに合ったものと呼ぶことができます。 そしてもちろん、ソースコードリポジトリで確認してください。







 kind: Deployment apiVersion: apps/v1beta1 metadata: name: web spec: strategy: type: RollingUpdate rollingUpdate: maxSurge: 1 maxUnavailable: 1 minReadySeconds: 10 replicas: 2 template: metadata: labels: app: web spec: containers: - image: gcr.io/my-project/my-app:latest name: my-app imagePullPolicy: Always ports: - containerPort: 4001 command: ["passenger", "start", "-p", "4001", "-e", "production", "--max-pool-size", "2", "--min-instances", "2", "--no-friendly-error-pages" "--max-request-queue-time", "10", "--max-request-time", "10", "--pool-idle-time", "0", "--memory-limit", "300"] env: - name: "RAILS_LOG_TO_STDOUT" value: "true" - name: "RAILS_ENV" value: "production" # ... obviously reduced the many ENV vars for brevity - name: "REDIS_URL" valueFrom: secretKeyRef: name: my-env key: REDIS_URL - name: "SMTP_USERNAME" valueFrom: secretKeyRef: name: my-env key: SMTP_USERNAME - name: "SMTP_PASSWORD" valueFrom: secretKeyRef: name: my-env key: SMTP_PASSWORD # ... this part below is mandatory for Cloud SQL - name: DB_HOST value: 127.0.0.1 - name: DB_PASSWORD valueFrom: secretKeyRef: name: cloudsql-db-credentials key: password - name: DB_USER valueFrom: secretKeyRef: name: cloudsql-db-credentials key: username - image: gcr.io/cloudsql-docker/gce-proxy:latest name: cloudsql-proxy command: ["/cloud_sql_proxy", "--dir=/cloudsql", "-instances=my-project:us-west1:my-db=tcp:5432", "-credential_file=/secrets/cloudsql/credentials.json"] volumeMounts: - name: cloudsql-instance-credentials mountPath: /secrets/cloudsql readOnly: true - name: ssl-certs mountPath: /etc/ssl/certs - name: cloudsql mountPath: /cloudsql volumes: - name: cloudsql-instance-credentials secret: secretName: cloudsql-instance-credentials - name: ssl-certs hostPath: path: /etc/ssl/certs - name: cloudsql emptyDir:
      
      





例について説明します。









 - name: "SMTP_USERNAME" valueFrom: secretKeyRef: name: my-env key: SMTP_USERNAME
      
      





これは、my-envという名前の「秘密」リポジトリへのリンクです。 そして、これはあなたがあなた自身を作成する方法です:







 kubectl create secret generic my-env \ --from-literal=REDIS_URL=redis://foo.com:18821 \ --from-literal=SMTP_USERNAME=foobar
      
      





コマンドラインからすべてを宣言するのではなく、テキストファイルをダウンロードできるため、ドキュメントをお読みください。







先ほど言ったように、データベースにはマネージドサービスを使用したいと思います。 Dockerイメージをアップロードできますが、お勧めしません。 同じことは、Redis、Mongoなどのデータベースなどの他のサービスにも当てはまります。 AWSを使用する場合、 Google Cloud SQLはRDSに似ていることに注意してください。







PostgreSQLのインスタンスを作成した後、Webアプリケーションから直接アクセスすることはできません。 2番目のDockerイメージ「CloudSQL Proxy」のテンプレートがあります。







これを行うには、最初にサービスアカウントを作成する必要があります。







 gcloud sql users create proxyuser host --instance=my-db --password=abcd1234
      
      





PostgreSQLインスタンスを作成した後、JSON資格情報をロードするように求められます。 どこかに保存します。 強力なパスワードが必要であることを思い出してはいけません。 追加の秘密を作成する必要があります。







 kubectl create secret generic cloudsql-instance-credentials \ --from-file=credentials.json=/home/myself/downloads/my-db-12345.json kubectl create secret generic cloudsql-db-credentials \ --from-literal=username=proxyuser --from-literal=password=abcd1234
      
      





これらは、展開のこの部分で言及されています。







 - image: gcr.io/cloudsql-docker/gce-proxy:latest name: cloudsql-proxy command: ["/cloud_sql_proxy", "--dir=/cloudsql", "-instances=my-project:us-west1:my-db=tcp:5432", "-credential_file=/secrets/cloudsql/credentials.json"] volumeMounts: - name: cloudsql-instance-credentials mountPath: /secrets/cloudsql readOnly: true - name: ssl-certs mountPath: /etc/ssl/certs - name: cloudsql mountPath: /cloudsql volumes: - name: cloudsql-instance-credentials secret: secretName: cloudsql-instance-credentials - name: ssl-certs hostPath: path: /etc/ssl/certs - name: cloudsql emptyDir:
      
      





データベース名(この場合はmy-db)をコマンドの-instanceに追加する必要があります。







ちなみに、 gce-proxy:latest



は、バージョン1.11が既に存在する場合にバージョン1.09を指します。 新しいバージョンでは、接続が切断され、待ち時間が長くなるという頭痛の種が作成されました。 したがって、私は新しいバージョン-1.09に戻り、すべてがうまくいきました。 だから、すべてが新しいわけではありません。 インフラストラクチャでは、安定性を厳守する方が適切です。







また、ポッドが1つのプロキシのみに接続できるように、各ポッドに個別のCloudSQLインスタンスをロードするのではなく、個別のCloudSQLインスタンスをロードするオプションも必要になる場合があります。 このスレッドをテーマについて読んでください。







サブルーチンが1つのプロキシのみに接続できるように、サブごとにCloudSQLのインスタンスを用意する代わりに、CloudSQLの個別のインスタンスをダウンロードできます。 この記事を読むことをお勧めします







何も影響を受けていないようです。 したがって、 ノードポートサービスを介してポッドを公開する必要があります。 deploy/web-svc.yamlfile



作成しましょう。







 apiVersion: v1 kind: Service metadata: name: web-svc spec: sessionAffinity: None ports: - port: 80 targetPort: 4001 protocol: TCP type: NodePort selector: app: web
      
      





これがspec:template:metadata:labels



の重要性を強調した理由です。 spec:selector



で使用して、正しいコンテナを選択します。







これらの2つのポッドを次のように拡張できます。







 kubectl create -f deploy/web.yml kubectl create -f deploy/web-svc.yml
      
      





ポッドがkubectl get pods --watch



を使用して作成されてkubectl get pods --watch



ます。







負荷分散



多くの教科書では、ハースはLoad Balancerと呼ばれる別のサービスを通じて提供されます。 彼が圧力下でどのように振る舞うか、SSL終了があるかどうかなどはわかりません。NGINXコントローラーを使用してIngress Load Balancerをフルにオンにすることにしました。







まず第一に、私はそれのために別のノードプールを作成することにしました、例えば:







 gcloud container node-pools create web-load-balancer \ --cluster=my-web-production \ --node-labels=role=load-balancer \ --machine-type=g1-small \ --num-nodes 1 \ --max-nodes 3 --min-nodes=1 \ --enable-autoscaling
      
      





large-pool



例が作成されたら、 large-pool



--node-labels



を追加してdefault-pool



代わりにコントローラーを設定しdefault-pool



。 ノードインスタンスの名前を知る必要があり、次のようにこれを行うことができます。







 $ gcloud compute instances list NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS gke-my-web-production-default-pool-123-123 us-west1-a n1-standard-4 10.128.0.1 123.123.123.12 RUNNING gke-my-web-production-large-pool-123-123 us-west1-a n1-highcpu-8 10.128.0.2 50.50.50.50 RUNNING gke-my-web-production-web-load-balancer-123-123 us-west1-a g1-small 10.128.0.3 70.70.70.70 RUNNING
      
      





保存してください:







export LB_INSTANCE_NAME=gke-my-web-production-web-load-balancer-123-123









外部IPアドレスを手動で予約し、名前を付けることができます。







 gcloud compute addresses create ip-web-production \ --ip-version=IPV4 \ --global
      
      





予約済みのIPアドレス「111.111.111.111」を生成したとします。 保存してください:







 export LB_ADDRESS_IP=$(gcloud compute addresses list | grep "ip-web-production" | awk '{print $3}')
      
      





アドレスを負荷分散ノードのインスタンスに関連付けます。







 export LB_INSTANCE_NAT=$(gcloud compute instances describe $LB_INSTANCE_NAME | grep -A3 networkInterfaces: | tail -n1 | awk -F': ' '{print $2}') gcloud compute instances delete-access-config $LB_INSTANCE_NAME \ --access-config-name "$LB_INSTANCE_NAT" gcloud compute instances add-access-config $LB_INSTANCE_NAME \ --access-config-name "$LB_INSTANCE_NAT" --address $LB_ADDRESS_IP
      
      





残りのIngress Deployment構成を追加します。 これには多くの時間がかかりますが、ほとんどはパターンに従います。 default-http-backend



という別のWebアプリケーションを定義することから始めましょう。 何らかの理由でWebコンテナが利用できない場合、HTTPリクエストに応答するために使用されます。 それをdeploy / default-web.yml



と呼びましょう:







 apiVersion: extensions/v1beta1 kind: Deployment metadata: name: default-http-backend spec: replicas: 1 template: metadata: labels: app: default-http-backend spec: terminationGracePeriodSeconds: 60 containers: - name: default-http-backend # Any image is permissable as long as: # 1. It serves a 404 page at / # 2. It serves 200 on a /healthz endpoint image: gcr.io/google_containers/defaultbackend:1.0 livenessProbe: httpGet: path: /healthz port: 8080 scheme: HTTP initialDelaySeconds: 30 timeoutSeconds: 5 ports: - containerPort: 8080 resources: limits: cpu: 10m memory: 20Mi requests: cpu: 10m memory: 20Mi
      
      





何も変更する必要はありません。 これで、展開パターンに精通しました。 NodePortを介してテンプレートを公開する必要があるため、 deploy/default-web-svc.yml



追加しましょう。







 kind: Service apiVersion: v1 metadata: name: default-http-backend spec: selector: app: default-http-backend ports: - protocol: TCP port: 80 targetPort: 8080 type: NodePort
      
      





繰り返しますが、何も変更しないでください。 次の3つのファイルは重要な部分です。 まず、NGINXロードバランサーを作成し、 deploy / nginx.yml



ます。







 apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nginx-ingress-controller spec: replicas: 1 template: metadata: labels: k8s-app: nginx-ingress-lb spec: # hostNetwork makes it possible to use ipv6 and to preserve the source IP correctly regardless of docker configuration # however, it is not a hard dependency of the nginx-ingress-controller itself and it may cause issues if port 10254 already is taken on the host # that said, since hostPort is broken on CNI (https://github.com/kubernetes/kubernetes/issues/31307) we have to use hostNetwork where CNI is used hostNetwork: true terminationGracePeriodSeconds: 60 nodeSelector: role: load-balancer containers: - args: - /nginx-ingress-controller - "--default-backend-service=$(POD_NAMESPACE)/default-http-backend" - "--default-ssl-certificate=$(POD_NAMESPACE)/cloudflare-secret" env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: POD_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace image: "gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.5" imagePullPolicy: Always livenessProbe: httpGet: path: /healthz port: 10254 scheme: HTTP initialDelaySeconds: 10 timeoutSeconds: 5 name: nginx-ingress-controller ports: - containerPort: 80 name: http protocol: TCP - containerPort: 443 name: https protocol: TCP volumeMounts: - mountPath: /etc/nginx-ssl/dhparam name: tls-dhparam-vol volumes: - name: tls-dhparam-vol secret: secretName: tls-dhparam
      
      





nodeSelector



は、新しいノードプールを作成したときに追加したノードラベルを作成することに注意してnodeSelector









タグ、レプリカの数を使用したい場合があります。 ここに、私がtls-dhparam-vol



と呼んだボリュームがマウントされていることに注意することが重要です。 これはDiffie Hellman Ephemeral Parameters



です。 生成します:







 sudo openssl dhparam -out ~/documents/dhparam.pem 2048 kubectl create secret generic tls-dhparam --from-file=/home/myself/documents/dhparam.pem kubectl create secret generic tls-dhparam --from-file=/home/myself/documents/dhparam.pem
      
      





コントローライメージにバージョン0.9.0-beta_5を使用していることに注意してください。 今のところ問題なく動作します。 ただし、リリースノートや新しいバージョンに注意して、独自のテストを行ってください。







繰り返しますが、負荷分散サービスを介してこのIngressコントローラーを公開しましょう。 deploy / nginx-svc.yml



と呼びましょう:







 apiVersion: v1 kind: Service metadata: name: nginx-ingress spec: type: LoadBalancer loadBalancerIP: 111.111.111.111 ports: - name: http port: 80 targetPort: http - name: https port: 443 targetPort: https selector: k8s-app: nginx-ingress-lb
      
      





上記で予約し、 LB_INGRESS_IP ENV var



保存した静的外部IPを覚えていますか? これをspec: loadBalancerIP



に含める必要がありますspec: loadBalancerIP



セクションこれは、DNSサービスに「レコード」として追加するIPアドレスでもあります(www.my-app.com.brをCloudFlareにマッピングするとしましょう)。







独自のIngress設定を作成できるようになりました。次のようにdeploy / ingress.yml



を作成しましょう。







 apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ingress annotations: kubernetes.io/ingress.class: "nginx" nginx.org/ssl-services: "web-svc" kubernetes.io/ingress.global-static-ip-name: ip-web-production ingress.kubernetes.io/ssl-redirect: "true" ingress.kubernetes.io/rewrite-target: / spec: tls: - hosts: - www.my-app.com.br secretName: cloudflare-secret rules: - host: www.my-app.com.br http: paths: - path: / backend: serviceName: web-svc servicePort: 80
      
      





したがって、Webモジュール用に作成されたNodePortサービスをnginxログインコントローラーに接続し、 spec: tls: secretName



介してSSL補完を追加しました。 作成方法は? まず、例としてCloudFlareを使用してSSL証明書を取得する必要があります。







購入時に、プロバイダーはダウンロード用の秘密ファイルを提供する必要があります(安全に保管してください!Dropboxのパブリックフォルダーは安全ではありません!)。 次に、次のようにインフラストラクチャに追加する必要があります。







 kubectl create secret tls cloudflare-secret \ --key ~/downloads/private.pem \ --cert ~/downloads/fullchain.pem
      
      





多くのファイルを編集したので、ロードバランシングパッケージ全体をデプロイできます。







 kubectl create -f deploy/default-web.yml kubectl create -f deploy/default-web-svc.yml kubectl create -f deploy/nginx.yml kubectl create -f deploy/nginx-svc.yml kubectl create -f deploy/ingress.yml
      
      





このNGINX Ingress設定は、 Zihao Zhangのブログ投稿に基づいています。 Kubernetインキュベーターリポジトリにも例があります 。 あなたはそれをチェックアウトできます。







すべて正しく行った場合、 https://www.my-app-com.brでWebアプリケーションがダウンロードされます。 次のように、CloudFlareを介して最初のバイト時間(TTFB)を確認できます。







 curl -vso /dev/null -w "Connect: %{time_connect} \n TTFB: %{time_starttransfer} \n Total time: %{time_total} \n" https://www.my-app.com.br
      
      





TTFBが遅い場合:







 curl --resolve www.my-app.com.br:443:111.111.111.111 https://www.my-app.com.br -svo /dev/null -k -w "Connect: %{time_connect} \n TTFB: %{time_starttransfer} \n Total time: %{time_total} \n"
      
      





TTFBは約1秒以下にする必要があります。 それ以外の場合、アプリケーションにエラーがあることを意味します。 マシンノードインスタンスのタイプ、1つのモジュールにロードされているワーカーの数、CloudSQLプロキシバージョン、NGINXコントローラーバージョンなどを確認する必要があります。これは試行錯誤の手順です。 洞察のためにローダーまたはWebページテストにサインアップします。







ローリング更新



すべてが機能するようになったので、冒頭で述べたローリングアップデートを更新するにはどうすればよいですか? 最初にコンテナレジストリリポジトリでgit push



を実行し、Dockerイメージが作成されるのを待ちます。







覚えておいて、トリガーにランダムなバージョン番号の画像を配置させましたか? それを使ってみましょう(Google CloudコンソールのContainer RegistryのBuild Historyリストで見ることができます):







 kubectl set image deployment web my-app=gcr.io/my-project/my-app:1238471234g123f534f543541gf5 --record
      
      





deploy/web.yml



宣言されているのと同じ名前とイメージを使用する必要があります。 ローリング更新が開始され、新しいモジュールが追加されてから、ブロックが完了します。すべてのユーザーがダウンタイムなしで更新されるまで、これらは完了します。







ローリング更新は慎重に実行する必要があります。 たとえば、展開にデータベースの移行が必要な場合は、メンテナンスウィンドウを追加する必要があります(トラフィックが少ない深夜に行う必要があります)。 したがって、移行コマンドは次のように実行できます。







 kubectl get pods # to get a pod name kubectl exec -it my-web-12324-121312 /app/bin/rails db:migrate # you can also bash to a pod like this, but remember that this is an ephemeral container, so file you edit and write there disappear on the next restart: kubectl exec -it my-web-12324-121312 bash
      
      





, -, :







 kubectl delete -f deploy/web.yml && kubectl apply -f deploy/web.yml
      
      





:



« » – / . Google Cloud . , . API .







SSD- :







 gcloud compute disks create --size 500GB my-data --type pd-ssd gcloud compute instances list
      
      





. , gke-my-web-app-default-pool-123-123



. my-data



:







 gcloud compute instances attach-disk gke-my-web-app-default-pool-123-123 --disk my-data --device-name my-data gcloud compute ssh gke-my-web-app-default-pool-123-123
      
      





ssh . sudo lsblk



, 500 , , / dev / sdb



. , , !







 sudo mkfs.ext4 -m 0 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/sdb
      
      





SSH :







 gcloud compute instances detach-disk gke-my-web-app-default-pool-123-123 --disk my-data
      
      





, yaml :







 spec: containers: - image: ... name: my-app volumeMounts: - name: my-data mountPath: /data # readOnly: true # ... volumes: - name: my-data gcePersistentDisk: pdName: my-data fsType: ext4
      
      





CronJob deploy / auto-snapshot.yml



:







 apiVersion: batch/v1beta1 kind: CronJob metadata: name: auto-snapshot spec: schedule: "0 4 * * *" concurrencyPolicy: Forbid jobTemplate: spec: template: spec: restartPolicy: OnFailure containers: - name: auto-snapshot image: grugnog/google-cloud-auto-snapshot command: ["/opt/entrypoint.sh"] env: - name: "GOOGLE_CLOUD_PROJECT" value: "my-project" - name: "GOOGLE_APPLICATION_CREDENTIALS" value: "/credential/credential.json" volumeMounts: - mountPath: /credential name: editor-credential volumes: - name: editor-credential secret: secretName: editor-credential
      
      





, IAM & admin Google Cloud, JSON , , :







 kubectl create secret generic editor-credential \ --from-file=credential.json=/home/myself/download/my-project-1212121.json
      
      





: cron. «0 4 *» , 4 .







.







, , . Kubernetes, Deployment, Service, Ingress, ReplicaSet, DaemonSet .







, multi-region High Availability, .







: My Notes about a Production-grade Ruby on Rails Deployment on Google Cloud Kubernetes Engine








All Articles