dockerはもう5年以上、GKEのkubernetesとminikubeは今年の春から使い始めた。
普段使う開発言語はdjango(python)なんやけど、どう扱えば改善・テスト・本番反映・利用がうまくいくかってことを考えてみた。
ちょうどインボイス対応でdjangoの処理書き換えるから、そのための消費税計算機能とかもつけるし。
開発はやっぱりローカルPCでのdocker
自分にはこれが一番しっくりくる。
本番環境のGCPにあるVMもこれと同じ。
フロントエンドマシンはmacやから、ubuntu22でssdドライブに置いたvmdkのデータ領域をsamba共有させてvscodeで編集。
vscodeのremote developmentって方法もあるけど、シンプルやなかったから使ってない。
+-local ubuntu22 linux VM-----+
| +-docker---------+ +-vmdk-+ |
| | +-container-+ | | data | |
| | | Django | | | d1 | |
| | +-----------+ | +------+ |
| | +-container-+ | | | |
| | | mariadb | | | d2 | |
| | +-----------+ | +------+ |
| | +-container-+ | | | |
| | | xrdp-ubu22| | | d3 | |
| | +-----------+ | +------+ |
| +----------------+ |
+-----------------------------+
GKE/EKSのkubernetesで動かすのはどんなとき?
s3にデータを溜め込んでるとか、機械学習で大量のデータを作ってpvにcsv置いてるとか、スケーラブルなサーバ運用したいならGKE/EKS使えばええ。
ただしスケールにも限界あるから、定期メンテナンスの日付や時間帯はサービス停止するように運用計画考える必要がある。
kubernetesで実際に動かすとしたら?
個人利用ではクラスタ構成なんか必要ない。
クラスタ構成ってのは、システムが粘り強く頑張って他のリージョンとかゾーンを使ってサービスが動く。
そのための設定とか、pv確保とかで何とかして動いてはくれるけど、水害で水浸しになってしばらく動かんとかになったら、手動でリージョン変えてVM作り直すし(春頃にフランスでGCPのサービスが長いこと止まってたかも)。
業務利用やったらPod内でコンテナのレプリカさせたり、pvをpvcで用意したり。
サーバの数とか規模が定義しづらくスケーラブルなほうがいいとき、コンテナ仮想化を本番利用するなら、kubernetes使えばいい。
webサーバやったら、kubernetesよりakamaiのcdnのほうがええかもしれん。
+--kubernetes --------------------+
| +-cluster ------+ +-pv--------+ |
| | | | +-data--+ | |
| | +-container-+ | | | | | |
| | | Django | | | | d1 | | |
| | +-----------+ | | +-------+ | |
| | +-container-+ | | | | | |
| | | mariadb | | | | d2 | | |
| | +-----------+ | | +-------+ | |
| | +-container-+ | | | | | |
| | | xrdp-ubu22| | | | d3 | | |
| | +-----------+ | | +-------+ | |
| | | +-----------+ |
| | +----LB ----+ | |
| | | | | |
| | +-----------+ | |
| +---------------+ |
+---------------------------------+
kubernetes使うとき考えたこと。
別で運用サーバを作って、クラスタが紐づくようにしてからマニフェストを置く
👉今動いてるPodとかサービスのマニフェストはどれやねん、ってならんようにルール決めたほうがええ。
ちょっと試す場合にcloud shell使って手軽にkubectlコマンドからやってもええけど、期間が過ぎたらcloud shellのデータ置き場は蒸発するから、マニフェスト置きっぱなしにして使わんほうがええ。
👉アプリケーションはgitlabとか使うやろけど、シェルとかkubectlで使うマニフェストもgitlabに入れたほうがええ。
👉クラスタとkubectlのバージョンはマメに上げてく
予算が許すなら、開発・検証・本番ってクラスタを分けて、運用サーバにも3つの環境用のユーザを作ったらブレへん
👉ノードもゾーンごとに置くとかしたらええし、開発・検証のクラスタを使わんときはノード数をゼロにしたら費用かからん。
👉pvは確保したディスクサイズで課金されるからゼロにはできんけど、tar.gzで固めて普段は逃しといて、使うときだけpvc/pvをデプロイでもええかもしれん。
👉予算がないなら、1つのクラスタで名前空間で分割したらええけど、1つのクラスタに全部入れたらkubernetesで障害発生したとき苦しいやろなぁ。
👉できればリージョンも別のところにしたほうがええかも。
👉ビルドの方法を変えるんやなくて、動かすモジュールは開発・検証・本番を同じにしておき、環境差異はdev/stg/prdとかconfigmapで変えられるほうがええ。
Podの中のコンテナをビルドするとき特殊なモジュールをapt-get/dnfで取ってくるなら、dockerビルドはローカルPCでやってGARにpush
👉企業の中のLANはプロキシ使ってることがあって、一般回線とデータ回線を分割してない上に昼間めっちゃ回線混んでたらビルドでタイムアウトとかありえる
👉apt-getはあんまり競合エラーって見たことないけど、redhat系やったらdnfは競合がよく発生する気がするし、さんざん待って発生したら心が折れる
👉途中でビルド失敗してもdockerは途中からやりなおしてくれることあるけど、dockerイメージ置き場が食いつぶされる
👉dockerビルドはマルチステージを使ったほうがイメージ小さくて済むこともある
👉もしもバージョン指定をdockerfileの中でやってるなら、ローカルPCでちゃんとビルドが通ることを確認してからサーバ作業したほうがええ
👉pipでタイムアウトとか競合があるとバージョン調整たいへんやから、requirement.txtもローカルPCでちゃんと警告とかエラー出んことを確認したほうがええ
👉GARにpushしてタグは複数つけておき、バージョンのタグ(Vx.x)とターゲットのタグ(例えばdev)をつけておいて、Podマニフェストにイメージを指定するときはターゲットのタグを書いておく
+--GAR------------------------------------------+
| +--django-----------------------------------+ |
| | +-image1----+ +-image2----+ +-image3----+ | |
| | | V3.2 | | V4.0 | | V4.2 dev| | |
| | +-----------+ +-----------+ +-----------+ | |
| +-------------------------------------------+ |
| +--mariadb----------------------------------+ |
| | +-image1----+ +-image2----+ +-image3----+ | |
| | | V10.3 | | V10.6 | | V10.11 dev| | |
| | +-----------+ +-----------+ +-----------+ | |
| +-------------------------------------------+ |
+-----------------------------------------------+
👉イメージを使ってテストに失敗したとき、前のバージョンのイメージを残しておけば、ターゲットのタグ付けを手動変更してPodをデプロイしなおしたら巻き戻せる
自分なりの工夫
👉ノードは日本のリージョンは使わず、USのリージョンを使う(自分が日本にいるから別の大陸のを使う)
👉gcpのGKEやったらgoogle driveにpvのバックアップをtar.gzして逃すと速い(遅いときもあるけど転送速度3000Mbpsとか平気で使える)
👉google driveに逃したら、rclone使うとローカルlinuxにスクリプト書いてrsyncっぽくデータ持ってこれる
👉GUIで持ってきたいならcyberduck使う
👉awsのEKSやったらs3使ってtar.gzを逃したらええんとちゃうかなぁ、rcloneとかcyberduck/winscpも使える
アップデート計画
kubernetesのバージョンはどんどん上がる
kubernetesのアップデートは4ヶ月に1回ぐらい上がってく。
1.23が2021-12-14に出たら、1.24は2022-05-03に出てる。
今は2023年9月で、2023-08-15に1.28が出てて、今月にはGKEのrapidチャンネルで使えるようになる。
minikubeでも9月1日頃に確認したら1.28.0-rc.1がクラスタとして使えるようになってた(kubectlと一緒にバージョン上げたらちゃんと使えた)。
たぶん2週間ぐらいして9月中旬になったら1.28.1とか使えるようになると思う。
アプリのテストは確実に
ローカルpcのdockerでは単体テスト、結合テストはGKE/EKSクラスタの中でやったほうがええ。
環境や予算が許さへんのやったら、minikubeをローカルPCで展開してkubernetes環境作ってテストしたらええ。
docker imageの置き場はGARにしといて、本番と開発を別で用意しておき、db接続先とか設定ファイルみたいなのはsecretとかconfigmapを参照する。
テストとか動作確認たいへんになるから、手早く確実に動作確認ができるシンプルな仕組みにしとかんとアカン。
jenkinsでgitlabからソース取ってきてビルドとテストを自動化できてたらベストかも。
厳密にしなくてもいいなら、webサービスにログインして、何か参照系と更新系の操作してデータベース操作するとか、一人で1分以内にテストができるように手順確立できてたらええ。
脆弱性対応
Podの中で動くコンテナでapt-getして使ってるモジュールに脆弱性見つかったときの緊急対応方法とかも確立したほうがええ。
もしも設計書あるなら、ミドルウェアとか利用モジュールのバージョンとかをちゃんと書いて残しておき、影響調査しやすくしといたほうがええ。
いきなり「CVSSが9超えてるから早よバージョン上げろや」とか言われても耐えられますように。
nistは読みづらいこともあるのでjvnとか時々見たらええ(nistのはリストめっちゃ多い)。
cvedetailsやとCVSSスコアの分布が見れるし、プロダクトで検索もできる。
イントラやったらいくらか猶予もらえるかもしれんけど、公開サーバやったらけっこうツラい対応やわぁ。