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アプリケーション。
- 自動スナップショット/バックアップを備えたマウント可能な永続ストレージ。
- 自動バックアップおよび読み取り専用インスタンスへの簡単なレプリケーションを備えた信頼できる管理データベース(Postgresql)。
- マネージドシークレットストレージソリューション(ENV Herokuサポートなど)。 プロダクション構成をソースコードに保存しないでください。
- カスタム展開インフラストラクチャを必要としないDockerイメージのサポート。
- 固定IPアドレスを必要とする統合のための静的外部IPアドレス。
- CloudFlareに接続できるようにSSLを終了します(CDNは必要ですが、十分ではありません。2018年には、DDoS保護が必要になります)。
- デフォルトでは十分なセキュリティがあります。つまり、理論的には、開くことを決定するまですべてがロックされます。
- データセンターのさまざまな地域およびゾーンでの高可用性。
シンプルなデモWebアプリケーションは簡単にデプロイできます。 しかし、私はデモを望んでいませんでした、私は長期的に生産のためのソリューションを望んでいました。
いくつかの初心者の問題:
- ドキュメントは非常に広範囲であり、探しているものを知っていればほとんどすべてを見つけることができます。 また、AzureとAWSはKubernetesにいくつかの違いを実装しているため、一部のドキュメントはGoogle Cloudに適用されず、その逆も同様です。
- アルファ、ベータ、および安定段階には多くの機能があります。 ドキュメントは理解できるように見えますが、ほんの数か月前のほとんどのチュートリアルは、意図したとおりに動作しない場合があります(Kubernetes 1.8.4-gke)。
- 同じ概念を参照する一連の単語があります。 語彙に慣れる必要があります。
- レゴを演奏していると想像してください。 詳細はさまざまな方法で組み合わされ、干渉される可能性がありますが、すべてを台無しにするのは非常に簡単です。 これは、要件を満たす独自の構成を作成できることを意味します。 しかし、ただコピーすることはできません。
- YAMLファイルとコマンドラインを使用してほぼすべてを実行できますが、構成を再利用すること(たとえば、作業環境や中間環境など)は簡単な作業ではありません。 パラメーター化可能で再利用可能なYAMLビットを処理するサードパーティツールがありますが、私はすべて手動で行います。 インフラストラクチャで自動化されたテンプレートを試してはいけません。テンプレートの機能を正確に知らないでください。
-
gcloud
とkubectl
2つの重いコマンドラインツールがありkubectl
。
もう一度思い出させてください。これはステップバイステップのガイドではありません 。 いくつかのステップに注釈を付けます。
スケーラブルなWeb層(Webアプリ自体)
最初に必要なのは、完全な12因子アプリです。
Ruby on Rails、Django、Laravel、Node.js(とにかく)であっても、これは共有アクセスを持たず、ローカルファイルシステムへの書き込みに依存しないアプリケーションでなければなりません。 インスタンスを個別に簡単に無効にして実行できるアプリケーション。 ローカルメモリまたはローカルファイルにセッションが存在しないようにする必要があります(セッションの近接を避けることをお勧めします)。 ローカルファイルシステムへのファイルアップロードはありません(必要に応じて、外部永続ストレージをマウントする必要があります)。常に、マネージドストレージサービスにバイナリストリームを送信することをお勧めします。
フィンガープリント資産を介してキャッシュを出力する適切なパイプラインが必要です(好むと好まざるとにかかわらず、RailsはAsset Pipelineですぐに使える最高のソリューションを提供しています)。
アプリケーションをインストルメントし、 New Relic RPMとRollbarを追加します。
2018年、SQLインジェクション(または他の入力)を使用して独自のコードを展開したくない、コードの周りで制御されていない評価、CSRFまたはXSSなどの場所がありません。 CIコンベヤー。 私は待つことができます...
これはチュートリアルではないため、Google Cloudに登録して、プロジェクト、地域、ゾーンを設定できると想定しています。
Google Cloudの主要な構造を理解するには少し時間がかかりました。
- アプリケーションに必要なすべてのカバーとして機能するプロジェクトから始めます。
- 次に、 「クラスター」を作成します。 たとえば、オフライン資料用に、本番、ステージングクラスター、Webクラスター、またはスプリットサービスクラスターがあるとします。
- クラスターには、他のすべてのコントローラーである「クラスターマスター」があります(
gcloud
およびkubectl
はAPIと対話します)。 - クラスターには、多くの「ノードのインスタンス」 、正しい「マシン」(正確にはVMインスタンス)があります。
- 各クラスターには、少なくとも1つの「ノードプール」 (「デフォルトプール」)もあります。これは、同じ構成と同じ「マシンタイプ」を持つノードインスタンスのコレクションです。
- 最後に、ノードの各インスタンスは、LXCなどの単純なコンテナーである1つ以上の「コンテナー」を起動します。 これがあなたのアプリケーションが本当にある場所です。
クラスターの作成例:
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:
例について説明します。
-
kind
とapiVersion
は重要です。ドキュメントに注意してください。変更される可能性があります。 これはDeploymentと呼ばれるものです。 以前はレプリケーションコントローラーがありました(古いチュートリアルにあります)が、もう使用されていません。 推奨事項: ReplicaSetを使用してください。 - スペードをスペードと呼び
web
。metadata:name
withweb
ます。spec:template:metadata:labels
に注意してspec:template:metadata:labels
ここで、各ブロックをlabelapp: web
ます。 後で「サービス」セクションでアイテムを選択できるようにする必要があります。 - 私には、ローリング更新を構成する
spec:strategy
があります。 -
spec:replicas
は、必要なハース数を通知します。 ホストプールのマシンタイプを手動で計算し、各アプリケーションのサーバーリソースを共有する必要があります。 - 「last」タグで作成したDockerイメージ。
spec: template: spec: container: image
ます。 - 本番構成でPassengerを使用しています( Phusionのドキュメントをご覧ください)
- spec:template:spec:container:envセクションでは、VAR ENVを実際の製造の秘密でオーバーライドできます。 値をエンコードするか、このデバイスを使用できます。
- 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