ナニコレ
個人的な備忘録です。忘れた時に手早く探せるように...随時加筆です。間違ってるところもあるかもしれないでの、間違ったらご指摘していらだければ幸いです。
抽象的なもの
以下のものはkubernetsのチュートリアルから引用:(個人的な理解も含めるので、間違ったらご指摘していらだければ幸いです)。
ホームページにあるように、k8sの特徴の一つはPlanet Scaleです。この特徴に相応しく、k8sの設計もまるで1個1個の惑星を繋いでいくようなものでした。
-
cluster
は全てのものを入れる容器のようなもの。バーチャルネットワークを作り、外部からアクセスできないようにする。-
control plane
はdeploymentを通してnodeなどを制御する中枢-
deployment
はどのようにnodeをコントロールするかの設定ファイルのようなもの
-
-
node
はk8sのwoker machine。仮想マシンでも物理マシンでも構わないようです。-
kubelet
はnodeとmasterの間の通信を担当するプロセス。podとコンテナの管理もしている。 -
pod
は実際にコンテナアプリを入れるもの- 中には複数のcontainerと共有スペース(volume)を持つことができる
- nodeに障害が発生した場合、podはclusterないの別のnodeにスケジュールされる
-
-
service
はどのようにpodを外部に公開するかを定義する抽象的概念- podは死んだり復活したりする(例えばnodeが死んだ時別のnodeにスケジュールする)ので、serviceは
LabelSelector
を使ってpodを抽象的に特定する。
- podは死んだり復活したりする(例えばnodeが死んだ時別のnodeにスケジュールする)ので、serviceは
-
minikube / kubernets
まずはこのページへ行ってインストール
そしてkubectl
に関して普通に入れていいですが、簡単なやりかたでminikube経由で入れる
minikube kubectl -- get po -A
そしてalias設定、.bashrc
などで永続化しても良さそう
alias kubectl="minikube kubectl --"
clusterを作る
minikube start
deploymentを作る
kubectl create deployment <deployment_name> --image=name:tag
local imageを使う
参考記事:https://miyazi888.hatenablog.com/entry/2022/05/22/194940
minikube image load image:tag
deploymentsの詳細を見る
何かを見る時はgo-templateを使って詳細を絞るのも良さそう。
参考記事:https://k69blog.com/posts/k8s_go_template/
kubectl describe deployments
deploymentのimageを更新
kubectl set image deployment/<deployment_name> <container_name>=image:tag
指定した revision まで rollback
参考記事:https://tech-lab.sios.jp/archives/18550
kubectl rollout undo deployment <deployment_name> --to-revision=1
gce
前提: gcloud というグーグルのcliをインストールしていること
auto pilotモードのclusterを作る
gcloud container clusters create-auto hello-cluster --region=<COMPUTE_REGION>
localからkubectlでgkeを操作できように
gcloud container clusters get-credentials gke-cloud-sql-quickstart --region us-central1
cloud buildを使ってソースコードからアプリをコンテナ化、そして出来たコンテナをArtifact Registoryなどのcloudにアップする。(すでにartifactにrepoが作成されている前提で話します)
artifactにpushするにはimage nameがかなり特徴的な書き方をしなければならない
# cloudbuild.yaml
steps: # steps で build して
- name: "gcr.io/cloud-builders/docker"
args:
[
"build",
"-t",
"<region>-docker.pkg.dev/<project_id>/<repo_name>/<dir_name>:tag",
"-f",
"./Dockerfile",
".",
]
images: "<region>-docker.pkg.dev/<project_id>/<directory>/image:tag" # images で自動 push
書き終わったら gcloud で実行
gcloud builds submit --config ./cloudbuild.yaml ./
そして、yamlを書いてdeployment、serviceを作ってapply、など、普通k8s作業に入るので割愛。ちゃんとconsoleで可視化されているので結構みやすいと見た。
別のgcpサービスと連携
主に cloud sql と Memorystore(redis) の連携
redis
まずはredis、redisは簡単で、redisのインスタンスをコンソール上で作れば直接VPCネットワーク経由で繋げられる(auto pilod限定かも、スタンダードは--enable-ip-aliasが必要らしい)
golangで例を挙げると
RDB = redis.NewClient(&redis.Options{
Addr: rdbURI,
})
ここの rdbURI を redis instanceのプライマリ エンドポイント
に置き換えれば直接つながる、とても楽。
cloud sql
cloud sqlは結構ややこしい。ここれは mysql の例を使う。
まずdocsに従ってcloud sql instanceを作る。
作り終わったらこちらのdocsを見ながら着実に進みましょう。
auto pilotなら前準備なしですが、スタンダートなら Workload Identity をまず有効にしないといけない。(しなくても別の方法で接続できますが、安全性が下がるってdocsにも書いてあった)
そして実際に手を動かす前に、少し手順のおさらいをしましょう。
大雑把に行くと、gkeとcloud sqlの連携はサービスアカウント(Service Account)
というものによって結び付けられている(binding)。
このサービスアカウント(以下グーグルの習慣に乗ってSAと呼ぶ)というのは、どのアプリがどのgcpのapiを使えるかを制御するもの(セキュリティ)。
そして中にはGSA
(google service account)というプロジェクト規模なものとKSA
(kubernetes service account)というgke規模なものがある。なので、gkeからcloud sqlをアクセスするには、まず
- cloud sqlをアクセスできる
GSA
を作る - sql操作する予定の
KSA
を作る -
GSA
とKSA
を結びつける(bind) - cloud-sql-proxyを使って接続
では参ろう(初見で結構苦戦した私でござる
まずGSAを作る
# まずアカウント作る
gcloud iam service-accounts create <GSA_account_name> --display-name="gsa account display name"
# cloud sqlの権限を付与
gcloud projects add-iam-policy-binding <YOUR_PROJECT_ID> \
--member="serviceAccount:<GSA_account_name>@<YOUR_PROJECT_ID>.iam.gserviceaccount.com" \
--role="roles/cloudsql.client"
# logging書き込み権限付与
gcloud projects add-iam-policy-binding <YOUR_PROJECT_ID> \
--member="serviceAccount:<GSA_account_name>@<YOUR_PROJECT_ID>.iam.gserviceaccount.com" \
--role="roles/logging.logWriter"
続いてyamlを書いてKSAを作る
# service-account.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: <YOUR-KSA-NAME>
書いたらcmdで実行
kubectl apply -f service-account.yaml
GSA と KSA の binding です
gcloud iam service-accounts add-iam-policy-binding \
--role="roles/iam.workloadIdentityUser" \
--member="serviceAccount:<YOUR_PROJECT_ID>.svc.id.goog[<YOUR-K8S-NAMESPACE>/<YOUR-KSA-NAME>]" \
<GSA_account_name>@<YOUR_PROJECT_ID>.iam.gserviceaccount.com
まだ終わってません、KSA側でもアノテーションをつけてバインドを完了させます
kubectl annotate serviceaccount \
<YOUR-KSA-NAME> \
iam.gke.io/gcp-service-account=<GSA_account_name>@<YOUR_PROJECT_ID>.iam.gserviceaccount.com
これで cli の作業は完了、これからは deployment の作業に入る
実際に繋ぐコードはgolangのgormを予想して書きます
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: <deployment-name>
spec:
selector:
matchLabels:
app: <app-lable>
template:
metadata:
labels:
app: <app-lable>
spec:
serviceAccountName: <YOUR-KSA-NAME>
containers:
- name: <your-container-name>
image: <your-image-url>
ports:
- containerPort: <expose-port>
env:
- name: PORT
value: "<expose-port>" # env の中は必ず文字列でなければいけない
- name: DB_URI # 実際に gorm で繋ぐためのものをかく、注意が必要なのは、cloud-sql-proxy使っているので直接localhostに繋ぎまず
value: "<username>:<password>@tcp(127.0.0.1:3306)/<db_name>?charset=utf8mb4&parseTime=true"
- name: cloud-sql-proxy # 重要: アプリのコンテナ以外、cloud-sql-proxyのコンテナが必要
image: gcr.io/cloudsql-docker/gce-proxy:latest # image は gce-proxy を使う、公式チュートリアルでは gcr.io/cloud-sql-connectors/cloud-sql-proxy:latest を使う文章もあったが、こっちの方がいいです
command:
- "/cloud_sql_proxy"
- "--log_debug_stdout=true"
# - "-enable_iam_login" # この行は普通使わない、自動IAMログインが必要のときだけつける、必要のない時につけちゃうと繋がらないので注意
- "-instances=<INSTANCE_CONNECTION_NAME>=tcp:3306"
securityContext:
runAsNonRoot: true
実際に繋ぐところのコードも見てみましょう。
公式は kubectl secret
を使って環境変数に値を付与しているが、別に直接書いても繋がるので、安全面を考慮しながら好みでいいと思う。
dbURI := os.Getenv("DB_URI")
db, err := gorm.Open(mysql.New(mysql.Config{
DSN: dbURI,
DontSupportRenameIndex: true,
DontSupportRenameColumn: true,
}), &gorm.Config{
DisableForeignKeyConstraintWhenMigrating: true,
CreateBatchSize: 1000,
})
これでkubectl apply -f deployment.yaml
すれば動くはずです。