エンジニアの知的生産術を読んでみた
インプットやアウトプットの方法に興味があったので読んでみた。
感想
日常の学びや仕事をしていく中で役立つことが書かれており、自分の中で言語化できていなかったり気づいていないことを知れてとても有意義な本だった。
特に第2章 やる気を出すにあるタスクに集中できない原因はまさにタイムリーな話だったので、早速仕事に取り入れて効果が出ており即効性を感じている(個人差はある)。
エンジニアとタイトルに書いているがインプットとアウトプットに悩んでいる人、全員に読んでほしい本だと感じた。
7章の中から気付かされることが1つでもあればそれが今後の学びにつながると思う。
以下、共感したところや学んだところをざっと書いてみた。
第1章 新しいことを学ぶには
「どうしてこんなやり方を思いついたのだろう、自分には思いつかないな、彼は天才なのかもしれないな」と思うがそれは自分が一番手前の箱しか見ていないから感じる。
シニアエンジニアと自分の差を比較してしまうのでひしひしと感じるな。。。
大学に入らなくてもcourseraやedx、放送大学があるな
参考書を選ぶコツ
大学の講義の参考図書に選定されている
正誤表が充実している
改訂されている・ロングセラーである
遅延評価的勉強法
知りたいところから学ぶ
結局Yak sharvingしていく
Matzのソースコードの読み方
面白そうなところをつまみ食い
目的をもって読む
ソースコードの読み方例
ソースコード読んでもhowしかわからない。whyの情報はコメントやコミットログ、過去のやり取りにある。
仕事でも他グループのPRを見ることで何がリリースされるのかや新しく施策を始めようとしていることを知れたので非常に良い経験になった。
写経について私も最近は前よりもやらなくなっているかな。
最近はHaskellを勉強していて関数型言語という今まで触ってきた言語とは考え方が異なるので写経している。
でも今まで触った言語と同じような考え方で良い言語ならもう写経はせずドキュメントをさらっと読む程度にするかも。
第2章 やる気を出す
以下3つは意識したら仕事で集中できるようになった。おすすめ。
タスクを細分化して、タスクを一つに絞る
やる気を損ねる大きな原因は、タスクを一つに絞れない。
タスクを選んだ後にやる気が出ない多い原因は、タスクが大きすぎること。
第3章 記憶を鍛えるには
インプットとアウトプットを繰り返すことが大事。
Ankiを使えば学習間隔決定アルゴリズムであるM2アルゴリズムを使って学習できる。
* 今度資格の勉強の時に使ってみよう
理解できないことを学ぼうとしない。
* 学ぼうとしているものを理解するステップが必要。
本を読んで情報を収集するだけではなく、集めた情報を積み上げてピラミッドを作る作業が必要。
* まさにインプットからのアウトプットの作業だ。
第4章 効率的に読むには
本を読むことの目的
娯楽
情報を見つけること
理解を組み立てること
読む速度を測ってみると良いらしい
読まずに知識を手に入れる
書評をwebで検索する
Whole Mind System これどうなんだ。自分は娯楽の側面もあるからこんな読書の仕方は嫌だな
仕事で必要に駆られて手にいれたい知識ならいいかもしれない
Whole Mind Systemの一部であるマインドマップの作成などはNotebookLMがやってくれそうなので、PDF版を購入して要約やマインドマップを書かせるのが良いかもしれない。
第5章 考えをまとめるには
書き出し方でとにかく書いて情報を出してみる。まずは5分間
100個くらい考えていることを書き出すことを目標にしてみる。
* これ0秒思考かなんかで読んだな。
出し切ったらKJ法で分類する。
第6章 アイデアを思いつくには
先入観を持たずに他人の話を聞くことは難しいので、まずは自分の話を聞くことから練習してみましょう
まさにその通りだと思う。内省できてから他人の話を素直に聞けるようになった。
難しい言葉を使わないで説明できるかは新卒の時の会社の先輩に言われたなぁ。
本当にその単語の意味を理解しているのか疑問を持った方が良い。
* これは共感した。下手に横文字を使いすぎるの良くない。
第7章 何を学ぶかを決めるには
何か学びたいという熱意の湧いてくる対象を見つけ、それを学べば良いのです。
自分の学びの原動力かも。無理に学びたくないもの学ばなくてもいいと思っている。
社会人がまず何を学ぶべきか、それは「今やっている仕事の効率化」です。しことを効率化することで時間の余裕を作り、その余裕を新たな学びに投資するのです。
確かに。残業ばかりしているので耳が痛い。定時に上がって学ぶ時間を確保するところからやらないとな。
nginx実践入門を読んでみた
nginxを業務で使うことになったので読んでみた。
第1章 nginxの概要とアーキテクチャ
nginxはc10k問題を解決するために開発された。 c10k問題とは1台のサーバが1万ものクライアントからの接続を同時に処理しようとするサーバの処理が追いつかなくなるというスケーラビリティの問題だそうだ。
nginxの最大の特徴は優れたスケーラビリティなのだそうだ。
nginxの用途 - テキストや画像といった静的なコンテンツの配信 - リバースプロキシとして動作させる
大量のプロセスを起動するとプロセス間コンテキストスイッチのオーバーヘッドが大きくなって性能が劣化する。
第2章 インストールと起動
インストールしたくないのでcompose.ymlを書いた。
services:
nginx:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./html:/usr/share/nginx/html:ro
command: nginx -g 'daemon off;'
Dockerは便利だ。
第3章 基本設定
nginx.confは相対パスで書いてあったので絶対パスに書き換えた。
worker_processes 1;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# Use the container's standard log directory so the file exists
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
server {
listen 80;
server_name localhost;
# Match the volume in compose.yml which mounts ./html to /usr/share/nginx/html
root /usr/share/nginx/html;
index index.html index.htm;
}
}
nginxは変数名の先頭に$をつけて表現する。
クエリストリングの値は$arg_属性名、HTTPヘッダの値は$http_フィールド名で使用できる。
serverディレクティブでIPアドレス、ポート、ホスト名ごとに別々の設定を持つ複数のHTTPサーバを動作させることができる。
バーチャルサーバと呼ばれる。
rootディレクティブで指定したディレクトリのパスがそのURIのルートにマッピングされる。
worker_processes ディレクティブ ワーカー数はCPUのコア数と同じ数にするのが良い。 パラメータにautoを指定することで、CPUのコア数を自動検出してコア数と同じにする。
パフォーマンスに影響する設定
- keepalive_timeout.
- nginxに常時接続しているクライアントに対するタイムアウト時間.
- sendfile.
- sendfile()システムコールを有効/無効にする.
- tcp_nopush.
- TCP_NOPUSHオプションを有効/無効にする.
- このオプションを使用するとおもっとも大きなパケットサイズでレスポンスヘッダとファイルの内容を送信でき、送信するパケット数を最小化できる。基本的に有効にしておく。
- open_file_cache.
- オープンしたファイルのキャッシュを有効/無効にする.
第4章 静的なWebサイトの構築
特に気になるところはなかった。
第5章 安全かつ高速なHTTPSサーバの構築
高速なTLSを実現するうえで使用となる数値がTTFBです。
TTFBを最小化する方法として3つのテクニック。
- HTTP/2, またはSPDYによる通信の高速化.
- TLSセッション再開によるハンドシェイクの高速化.
- OCSPステープリングによるサーバ証明書検証コストの削減.
現在は以下のテクニックが必要だそうだ。Claudeに聞いてみた。
2025年時点での追加テクニック.
TLS 1.3を使う(必須).
- ハンドシェイクが高速化.
- 古い暗号スイートを排除.
HTTP/3 (QUIC)の検討.
- 0-RTT接続再開.
- パケットロスに強い.
Early Hints (103ステータス).
- ブラウザにリソースのプリロードを早期通知.
TLS証明書の最適化.
- ECDSA証明書(RSAより軽量).
- 証明書チェーンの最小化.
BBRやTCP Fast Open.
- カーネルレベルの最適化.
今(2025年)の情報をもとに安全かつ高速なHTTPSサーバの構築を構築すると下記のようになる。
第6章 Webアプリケーションサーバの構築
リバースプロキシの役割.
- ロードバランス.
- コンテンツキャッシュ.
- HTTPS通信の終端化.
nginxでリクエストをプロキシするにはproxy_passディレクティブを指定する
プロキシする際に指定すべきヘッダ
下記の設定はどこでも使われている可能性がある。
自分が見たnginxのconfigファイルには書いてあった
| ヘッダフィールド名 | 指定するパラメータ | 説明 |
|---|---|---|
| X-Forwarded-Host | $host | ユーザのリクエストに含まれるホスト名を指定する |
| X-Forwarded-For | $proxy_add_x_for_warded_for | リクエストが経由したアドレスを全て指定する |
| X-Forwarded-Proto | $scheme | ユーザのリクエストが使用したHTTPスキームを指定する |
本書で記載されているphp-fpm.confは足りない部分があったので補完した。
[www] listen = /var/run/php-fpm.sock listen.owner = nginx listen.group = nginx listen.mode = 0660 user = nginx group = nginx pm = dynamic pm.max_children = 8 pm.start_servers = 4 pm.min_spare_servers = 2 pm.max_spare_servers = 4 pm.max_requests = 500 ; security security.limit_extensions = .php ; timeouts request_terminate_timeout = 30s request_slowlog_timeout = 10s slowlog = /var/log/php-fpm/slow.log ; logging catch_workers_output = yes php_admin_value[error_log] = /var/log/php-fpm/error.log php_admin_flag[log_errors] = on ; process management pm.process_idle_timeout = 10s pm.max_spawn_rate = 32 ; status page (optional) pm.status_path = /status ping.path = /ping ping.response = pong
以下が必須項目.
1. listen.owner/group/mode - ソケットファイルのパーミッション。これがないとnginxがアクセスできない.
2. user/group - PHP-FPMの実行ユーザー。セキュリティ上重要.
3. security.limit_extensions - .php以外の実行を防ぐ。セキュリティ必須.
以下項目ほぼ必須.
4. request_terminate_timeout - 暴走スクリプト対策.
5. catch_workers_output - アプリのエラーをログに出力.
6. slowlog - パフォーマンス問題の調査に必須.
第7章 大規模コンテンツ配信サーバの構築
以下の3つが比較的問題になりやすいリソース
確かにオブザーバビリティの面でよく取り扱われる.
- CPU.
- ディスク I/O.
- ネットワーク.
負荷を確認する際によく利用するコマンド.
- top).
- dstat
- ss -s.
ssコマンドの代わりにnetstatコマンドを使う場合もある。
スケーリングを行う方法は以下の2つが考えられる 1. キャッシュサーバーにディスクを増設してスケールアップする 2. 新たにキャッシュサーバを追加する
第8章 Webサーバの運用とメトリクスモニタリング
fluentdの勉強
エンジニア養成読本シリーズ
上の本は古いので今勉強するならこれがいいかも
公式ドキュメント
少し古いが全体的にまとめて色々な技術学ぶならこれかな
以下のツールを解析でおすすめされたが今は使われているのだろうか?
Norikra
GrowthForecat
より進んだ解析を行うために、ログをHDFSやAmazon Redshift, Google BigQuery, Treasure Dateに出力し、長期間の集計を行うことが必要。
第9章 Luaによるnginxの拡張
Luaを使ってのnginxの拡張は今は使わないので斜め読み程度にとどめた。 ngx_luaを使うらしい。
第10章 OpenResty
初めて聞くフレームワークなのとあまり使われてなさそうなので流し読みした。
まとめ
Nginxのファイルを読む時に少しは抵抗感がなくなった気がする。
Nginxを用いたアーキテクチャを考える時にリファレンス的に使えるかもしれない。
早速会社のconfファイルを眺めてみよう。
kubernetes-the-hard-way-on-proxmox をやってみた
動機
RAM32GBの中華製ミニデスクトップを買ったので、Kubernetesの学習に良いらしいのでやってみた。
Prerequisites
概要

gatewayのネットワークドライブは2つ用意して、ローカルのネットワーク環境とKubernetesのネットワーク環境を用意する。
Installing the Client Tools
概要
cfsslとkubectlをインストールする。
cfsslとは github.com 秘密鍵ファイルや証明書ファイルの発行に必要なファイルを作成してくれる https://zenn.dev/hiro345/articles/20241201_advent_calendar_2024_14
kubectl kubernetes.io
Provisioning Compute Resources
概要
各ノード間の通信テストやgateway-01のFWルールや各ノード間の/etc/hostsファイルの設定をする。
- 下記のtmuxコマンドは全てのペインに同じコマンドを送信できて便利
[prefix]Ctrl+b then : setw synchronize-panes on
- for文でipぶん回すのインフラエンジニアっぽい
ubuntu@gateway-01:~$ for i in 10 11 12 20 21 22; do echo "Testing 192.168.8.$i"; ping -c 2 192.168.8.$i; done Testing 192.168.8.10 PING 192.168.8.10 (192.168.8.10) 56(84) bytes of data. 64 bytes from 192.168.8.10: icmp_seq=1 ttl=64 time=0.190 ms 64 bytes from 192.168.8.10: icmp_seq=2 ttl=64 time=0.299 ms --- 192.168.8.10 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1030ms rtt min/avg/max/mdev = 0.190/0.244/0.299/0.054 ms Testing 192.168.8.11 PING 192.168.8.11 (192.168.8.11) 56(84) bytes of data. 64 bytes from 192.168.8.11: icmp_seq=1 ttl=64 time=0.141 ms 64 bytes from 192.168.8.11: icmp_seq=2 ttl=64 time=0.222 ms --- 192.168.8.11 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1022ms rtt min/avg/max/mdev = 0.141/0.181/0.222/0.040 ms Testing 192.168.8.12 PING 192.168.8.12 (192.168.8.12) 56(84) bytes of data. 64 bytes from 192.168.8.12: icmp_seq=1 ttl=64 time=0.158 ms 64 bytes from 192.168.8.12: icmp_seq=2 ttl=64 time=0.272 ms --- 192.168.8.12 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1021ms rtt min/avg/max/mdev = 0.158/0.215/0.272/0.057 ms Testing 192.168.8.20 PING 192.168.8.20 (192.168.8.20) 56(84) bytes of data. 64 bytes from 192.168.8.20: icmp_seq=1 ttl=64 time=0.157 ms 64 bytes from 192.168.8.20: icmp_seq=2 ttl=64 time=0.249 ms --- 192.168.8.20 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1021ms rtt min/avg/max/mdev = 0.157/0.203/0.249/0.046 ms Testing 192.168.8.21 PING 192.168.8.21 (192.168.8.21) 56(84) bytes of data. 64 bytes from 192.168.8.21: icmp_seq=1 ttl=64 time=0.153 ms 64 bytes from 192.168.8.21: icmp_seq=2 ttl=64 time=0.335 ms --- 192.168.8.21 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1021ms rtt min/avg/max/mdev = 0.153/0.244/0.335/0.091 ms Testing 192.168.8.22 PING 192.168.8.22 (192.168.8.22) 56(84) bytes of data. 64 bytes from 192.168.8.22: icmp_seq=1 ttl=64 time=0.164 ms 64 bytes from 192.168.8.22: icmp_seq=2 ttl=64 time=0.242 ms --- 192.168.8.22 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1021ms rtt min/avg/max/mdev = 0.164/0.203/0.242/0.039 ms
Provisioning a CA and Generating TLS Certificates
概要
このステップでは以下を実施します:
1. Certificate Authority (CA) の作成
2. コンポーネント用のTLS証明書の生成:
- Admin用クライアント証明書.
- Kubelet用クライアント証明書(各ワーカーノード).
- Controller Manager用クライアント証明書.
- Kube Proxy用クライアント証明書.
- Scheduler用クライアント証明書.
- Kubernetes APIサーバー用証明書.
- Service Account用キーペア.
なぜ証明書が必要?
Kubernetesのコンポーネント間通信は全て暗号化され、相互に認証される必要がある:
- APIサーバー ↔ etcd.
- APIサーバー ↔ kubelet.
- kubectl ↔ APIサーバー.
- など.
- CA設定ファイルの作成
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "8760h"
},
"profiles": {
"kubernetes": {
"usages": ["signing", "key encipherment", "server auth", "client auth"],
"expiry": "8760h"
}
}
}
}
EOF
cat > ca-csr.json <<EOF
{
"CN": "Kubernetes",
"Key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "JP",
"L": "Tokyo",
"O": "Kubernetes",
"OU": "CA",
"ST": "Tokyo",
}
]
}
EOF
- CA証明書と秘密鍵を生成
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
- Admin用クライアント証明書
cat > admin-csr.json <<EOF
{
"CN": "admin",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "JP",
"L": "Tokyo",
"O": "system:masters",
"OU": "Kubernetes The Hard Way",
"ST": "Tokyo"
}
]
}
EOF
- 証明書を作成
cfssl gencert \ -ca=ca.pem \ -ca-key=ca-key.pem \ -config=ca-config.json \ -profile=kubernetes \ admin-csr.json | cfssljson -bare admin
- Kubelet用クライアント証明書.
- worker-0
cat > worker-0-csr.json <<EOF
{
"CN": "system:node:worker-0",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "JP",
"L": "Tokyo",
"O": "system:nodes",
"OU": "Kubernetes The Hard Way",
"ST": "Tokyo"
}
]
}
EOF
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-hostname=worker-0,192.168.8.20 \
-profile=kubernetes \
worker-0-csr.json | cfssljson -bare worker-0
- Controller Manager用クライアント証明書
cat > kube-controller-manager-csr.json <<EOF
{
"CN": "system:kube-controller-manager",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "JP",
"L": "Tokyo",
"O": "system:kube-controller-manager",
"OU": "Kubernetes The Hard Way",
"ST": "Tokyo"
}
]
}
EOF
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager
- Kube Proxy用クライアント証明書
cat > kube-proxy-csr.json <<EOF
{
"CN": "system:kube-proxy",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "JP",
"L": "Tokyo",
"O": "system:node-proxier",
"OU": "Kubernetes The Hard Way",
"ST": "Tokyo"
}
]
}
EOF
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
kube-proxy-csr.json | cfssljson -bare kube-proxy
- Scheduler用クライアント証明書
cat > kube-scheduler-csr.json <<EOF
{
"CN": "system:kube-scheduler",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "JP",
"L": "Tokyo",
"O": "system:kube-scheduler",
"OU": "Kubernetes The Hard Way",
"ST": "Tokyo"
}
]
}
EOF
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
kube-scheduler-csr.json | cfssljson -bare kube-scheduler
- Kubernetes APIサーバー用証明書
KUBERNETES_HOSTNAMES=kubernetes,kubernetes.default,kubernetes.default.svc,kubernetes.default.svc.cluster,kubernetes.svc.cluster.local
cat > kubernetes-csr.json <<EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "JP",
"L": "Tokyo",
"O": "kubernetes",
"OU": "Kubernetes The Hard Way",
"ST": "Tokyo"
}
]
}
EOF
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-hostname=10.32.0.1,192.168.8.10,192.168.8.11,192.168.8.12,192.168.8.1,192.168.3.18,127.0.0.1,${KUBERNETES_HOSTNAMES} \
-profile=kubernetes \
kubernetes-csr.json | cfssljson -bare kubernetes
- Service Account用キーペア
cat > service-account-csr.json <<EOF
{
"CN": "service-accounts",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "JP",
"L": "Tokyo",
"O": "Kubernetes",
"OU": "Kubernetes The Hard Way",
"ST": "Tokyo"
}
]
}
EOF
cfssl gencert \
-ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes \
service-account-csr.json | cfssljson -bare service-account
Generating Kubernetes Configuration Files for Authentication
概要
kubelet,kube-proxy,kube-scheduler,admin用にkubeconfigファイルを作成する。
kubeconfigファイルは、Kubernetesクラスターへの接続情報を含む設定ファイル。
各コンポーネントが使用するkubeconfigには以下の情報が含まれる:
- クラスター情報(APIサーバーのアドレス、CA証明書).
- ユーザー認証情報(クライアント証明書、秘密鍵).
- コンテキスト(どのクラスターにどのユーザーで接続するか).
- Kubernetes APIサーバーのアドレス設定
KUBERNETES_PUBLIC_ADDRESS=192.168.3.18
- kubelet用kubeconfigの生成
- worker-0用
kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=https://${KUBERNETES_PUBLIC_ADDRESS}:6443 \
--kubeconfig=worker-0.kubeconfig
kubectl config set-credentials system:node:worker-0 \
--client-certificate=worker-0.pem \
--client-key=worker-0-key.pem \
--embed-certs=true \
--kubeconfig=worker-0.kubeconfig
kubectl config set-context default \
--cluster=kubernetes-the-hard-way \
--user=system:node:worker-0 \
--kubeconfig=worker-0.kubeconfig
kubectl config use-context default --kubeconfig=worker-0.kubeconfig
- kube-proxy用kubeconfigの生成
kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=https://${KUBERNETES_PUBLIC_ADDRESS}:6443 \
--kubeconfig=kube-proxy.kubeconfig
kubectl config set-credentials system:kube-proxy \
--client-certificate=kube-proxy.pem \
--client-key=kube-proxy-key.pem \
--embed-certs=true \
--kubeconfig=kube-proxy.kubeconfig
kubectl config set-context default \
--cluster=kubernetes-the-hard-way \
--user=system:kube-proxy \
--kubeconfig=kube-proxy.kubeconfig
kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig
- kube-controller-manager用kubeconfigの生成
kubectl config set-cluster kubernetes-the-hard-way \ --certificate-authority=ca.pem \ --embed-certs=true \ --server=https://127.0.0.1:6443 \ --kubeconfig=kube-controller-manager.kubeconfig kubectl config set-credentials system:kube-controller-manager \ --client-certificate=kube-controller-manager.pem \ --client-key=kube-controller-manager-key.pem \ --embed-certs=true \ --kubeconfig=kube-controller-manager.kubeconfig kubectl config set-context default \ --cluster=kubernetes-the-hard-way \ --user=system:kube-controller-manager \ --kubeconfig=kube-controller-manager.kubeconfig kubectl config use-context default --kubeconfig=kube-controller-manager.kubeconfig
- kube-scheduler用kubeconfigの生成
kubectl config set-cluster kubernetes-the-hard-way \ --certificate-authority=ca.pem \ --embed-certs=true \ --server=https://127.0.0.1:6443 \ --kubeconfig=kube-scheduler.kubeconfig kubectl config set-credentials system:kube-scheduler \ --client-certificate=kube-scheduler.pem \ --client-key=kube-scheduler-key.pem \ --embed-certs=true \ --kubeconfig=kube-scheduler.kubeconfig kubectl config set-context default \ --cluster=kubernetes-the-hard-way \ --user=system:kube-scheduler \ --kubeconfig=kube-scheduler.kubeconfig kubectl config use-context default --kubeconfig=kube-scheduler.kubeconfig
- admin用kubeconfigの生成
kubectl config set-cluster kubernetes-the-hard-way \
--certificate-authority=ca.pem \
--embed-certs=true \
--server=https://${KUBERNETES_PUBLIC_ADDRESS}:6443 \
--kubeconfig=admin.kubeconfig
kubectl config set-credentials admin \
--client-certificate=admin.pem \
--client-key=admin-key.pem \
--embed-certs=true \
--kubeconfig=admin.kubeconfig
kubectl config set-context default \
--cluster=kubernetes-the-hard-way \
--user=admin \
--kubeconfig=admin.kubeconfig
kubectl config use-context default --kubeconfig=admin.kubeconfig
Generating the Data Encryption Config and Key
概要
暗号化キーの生成と暗号化設定ファイルを作成する。
Kubernetesは、etcdに保存される機密情報(Secrets)を暗号化できる。
これにより:
- etcdのバックアップが漏洩しても、Secretの内容は保護される.
- etcdに直接アクセスされても、データは暗号化されている.
- 暗号化キーの生成
ENCPYPTION_KEY=$(head -c 32 /dev/urandom | base64) echo $ENCPYPTION_KEY
- 暗号化設定ファイルの作成
cat > encryption-config.yaml <<EOF
kind: EncryptionConfig
apiVersion: v1
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: ${ENCPYPTION_KEY}
- identity: {}
EOF
Bootstrapping the etcd Cluster
概要
etcdは、Kubernetesの全てのクラスター状態を保存する分散キーバリューストア。
このステップでは:
1. 必要なファイルをcontrollerノードに配布.
2. etcdバイナリのダウンロード・インストール.
3. 3ノード構成の高可用性etcdクラスターを構築.
- 証明書とファイルの配布
# controller-0への配布 scp ca.pem kubernetes-key.pem kubernetes.pem ubuntu@192.168.8.10:~/ # controller-1への配布 scp ca.pem kubernetes-key.pem kubernetes.pem ubuntu@192.168.8.11:~/ # controller-2への配布 scp ca.pem kubernetes-key.pem kubernetes.pem ubuntu@192.168.8.12:~/ --- ubuntu@gateway-01:~/k8s-certs$ scp ca.pem kubernetes-key.pem kubernetes.pem ubuntu@192.168.8.10:~/ ca.pem 100% 1306 1.9MB/s 00:00 kubernetes-key.pem 100% 1679 3.6MB/s 00:00 kubernetes.pem 100% 1659 4.4MB/s 00:00 ubuntu@gateway-01:~/k8s-certs$ scp ca.pem kubernetes-key.pem kubernetes.pem ubuntu@192.168.8.11:~/ ca.pem 100% 1306 3.4MB/s 00:00 kubernetes-key.pem 100% 1679 5.6MB/s 00:00 kubernetes.pem 100% 1659 7.9MB/s 00:00 ubuntu@gateway-01:~/k8s-certs$ scp ca.pem kubernetes-key.pem kubernetes.pem ubuntu@192.168.8.12:~/ ca.pem 100% 1306 3.6MB/s 00:00 kubernetes-key.pem 100% 1679 6.7MB/s 00:00 kubernetes.pem 100% 1659 7.0MB/s 00:00 ubuntu@gateway-01:~/k8s-certs$
- ウィンドウを分割して、etcdバイナリのダウンロードとインストール
wget -q --show-progress --https-only --timestamping \ "https://github.com/etcd-io/etcd/releases/download/v3.5.12/etcd-v3.5.12-linux-amd64.tar.gz" tar -xvf etcd-v3.5.12-linux-amd64.tar.gz sudo mv etcd-v3.5.12-linux-amd64/etcd* /usr/local/bin/ etcd --version etcdctl version --- # controller-0の出力 ubuntu@controller-0:~$ wget -q --show-progress --https-only --timestamping \ "https://github.com/etcd-io/etcd/releases/download/v3.5.12/etcd-v3.5.12-linux-amd64.tar.gz" etcd-v3.5.12-linux-amd64.tar 100%[=============================================>] 19.40M 17.9MB/s in 1.1s ubuntu@controller-0:~$ ll total 19912 drwxr-x--- 4 ubuntu ubuntu 4096 Oct 20 21:54 ./ drwxr-xr-x 3 root root 4096 Oct 14 21:45 ../ -rw------- 1 ubuntu ubuntu 827 Oct 17 22:11 .bash_history -rw-r--r-- 1 ubuntu ubuntu 220 Jan 6 2022 .bash_logout -rw-r--r-- 1 ubuntu ubuntu 3771 Jan 6 2022 .bashrc drwx------ 2 ubuntu ubuntu 4096 Oct 14 21:45 .cache/ -rw-rw-r-- 1 ubuntu ubuntu 1306 Oct 20 21:46 ca.pem -rw-rw-r-- 1 ubuntu ubuntu 20337842 Jan 31 2024 etcd-v3.5.12-linux-amd64.tar.gz -rw------- 1 ubuntu ubuntu 1679 Oct 20 21:46 kubernetes-key.pem -rw-rw-r-- 1 ubuntu ubuntu 1659 Oct 20 21:46 kubernetes.pem -rw-r--r-- 1 ubuntu ubuntu 807 Jan 6 2022 .profile drwx------ 2 ubuntu ubuntu 4096 Oct 14 21:45 .ssh/ -rw-r--r-- 1 ubuntu ubuntu 0 Oct 14 21:50 .sudo_as_admin_successful -rw-rw-r-- 1 ubuntu ubuntu 165 Oct 20 21:54 .wget-hsts ubuntu@controller-0:~$ tar -xvf etcd-v3.5.12-linux-amd64.tar.gz etcd-v3.5.12-linux-amd64/ etcd-v3.5.12-linux-amd64/README.md etcd-v3.5.12-linux-amd64/READMEv2-etcdctl.md etcd-v3.5.12-linux-amd64/etcdutl etcd-v3.5.12-linux-amd64/etcdctl etcd-v3.5.12-linux-amd64/Documentation/ etcd-v3.5.12-linux-amd64/Documentation/README.md etcd-v3.5.12-linux-amd64/Documentation/dev-guide/ etcd-v3.5.12-linux-amd64/Documentation/dev-guide/apispec/ etcd-v3.5.12-linux-amd64/Documentation/dev-guide/apispec/swagger/ etcd-v3.5.12-linux-amd64/Documentation/dev-guide/apispec/swagger/v3election.swagger.json etcd-v3.5.12-linux-amd64/Documentation/dev-guide/apispec/swagger/rpc.swagger.json etcd-v3.5.12-linux-amd64/Documentation/dev-guide/apispec/swagger/v3lock.swagger.json etcd-v3.5.12-linux-amd64/README-etcdutl.md etcd-v3.5.12-linux-amd64/README-etcdctl.md etcd-v3.5.12-linux-amd64/etcd ubuntu@controller-0:~$ sudo mv etcd-v3.5.12-linux-amd64/etcd* /usr/local/bin/ [sudo] password for ubuntu: ubuntu@controller-0:~$ etcd --version etcdctl version etcd Version: 3.5.12 Git SHA: e7b3bb6cc Go Version: go1.20.13 Go OS/Arch: linux/amd64 etcdctl version: 3.5.12 API version: 3.5 ubuntu@controller-0:~$
- etcdの設定
# 設定ディレクトリとデータディレクトリの作成 sudo mkdir -p /etc/etcd /var/lib/etcd sudo chmod 700 /var/lib/etcd # 証明書のコピー sudo cp ~/ca.pem ~/kubernetes-key.pem ~/kubernetes.pem /etc/etcd/ --- # controller-0の出力 cpで途中入力を求められたが無事に/etc/etcdにコピーされている ubuntu@controller-0:~$ sudo mkdir -p /etc/etcd /var/lib/etcd ubuntu@controller-0:~$ sudo chmod 700 /var/lib/etcd ubuntu@controller-0:~$ sudo cp ~/ca.pem ~/kubernetes-key.pem ~/kubernetes.pem /etc/etcd/ > > ^C ubuntu@controller-0:~$ ll total 19916 drwxr-x--- 5 ubuntu ubuntu 4096 Oct 20 21:55 ./ drwxr-xr-x 3 root root 4096 Oct 14 21:45 ../ -rw------- 1 ubuntu ubuntu 827 Oct 17 22:11 .bash_history -rw-r--r-- 1 ubuntu ubuntu 220 Jan 6 2022 .bash_logout -rw-r--r-- 1 ubuntu ubuntu 3771 Jan 6 2022 .bashrc drwx------ 2 ubuntu ubuntu 4096 Oct 14 21:45 .cache/ -rw-rw-r-- 1 ubuntu ubuntu 1306 Oct 20 21:46 ca.pem drwxr-xr-x 3 ubuntu ubuntu 4096 Oct 20 21:55 etcd-v3.5.12-linux-amd64/ -rw-rw-r-- 1 ubuntu ubuntu 20337842 Jan 31 2024 etcd-v3.5.12-linux-amd64.tar.gz -rw------- 1 ubuntu ubuntu 1679 Oct 20 21:46 kubernetes-key.pem -rw-rw-r-- 1 ubuntu ubuntu 1659 Oct 20 21:46 kubernetes.pem -rw-r--r-- 1 ubuntu ubuntu 807 Jan 6 2022 .profile drwx------ 2 ubuntu ubuntu 4096 Oct 14 21:45 .ssh/ -rw-r--r-- 1 ubuntu ubuntu 0 Oct 14 21:50 .sudo_as_admin_successful -rw-rw-r-- 1 ubuntu ubuntu 165 Oct 20 21:54 .wget-hsts ubuntu@controller-0:~$ ll /etc/etcd total 20 drwxr-xr-x 2 root root 4096 Oct 20 21:59 ./ drwxr-xr-x 97 root root 4096 Oct 20 21:59 ../ -rw-r--r-- 1 root root 1306 Oct 20 21:59 ca.pem -rw------- 1 root root 1679 Oct 20 21:59 kubernetes-key.pem -rw-r--r-- 1 root root 1659 Oct 20 21:59 kubernetes.pem ubuntu@controller-0:~$
etcdのsystemdサービスファイル作成 同期モードは一時解除
controller-0での作業
INTERNAL_IP=192.168.8.10
ETCD_NAME=controller-0
cat <<EOF | sudo tee /etc/systemd/system/etcd.service
[Unit]
Description=etcd
Documentation=https://github.cm/coreos
[Service]
Type=notify
ExecStart=/usr/local/bin/etcd \\
--name ${ETCD_NAME} \\
--cert-file=/etc/etcd/kubernetes.pem \\
--key-file=/etc/etcd/kubernetes-key.pem \\
--peer-cert-file=/etc/etcd/kubernetes.pem \\
--peer-key-file=/etc/etcd/kubernetes-key.pem \\
--trusted-ca-file=/etc/etcd/ca.pem \\
--peer-trusted-ca-file=/etc/etcd/ca.pem \\
--peer-client-cert-auth \\
--client-cert-auth \\
--initial-advertise-peer-urls https://${INTERNAL_IP}:2380 \\
--listen-peer-urls https://${INTERNAL_IP}:2380 \\
--listen-client-urls https://${INTERNAL_IP}:2379,https://127.0.0.1:2379 \\
--advertise-client-urls https://${INTERNAL_IP}:2379 \\
--initial-cluster-token etcd-cluster-0 \\
--initial-cluster controller-0=https://192.168.8.10:2380,controller-1=https://192.168.8.11:2380,controller-2=https://192.168.8.12:2380 \\
--initial-cluster-state new \\
--data-dir=/var/lib/etcd
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
etcdサービスの起動 同期モードを有効化しておく
全controllerノードで同時実行
sudo systemctl daemon-reload
sudo systemctl enable etcd
sudo systemctl start etcd
sudo systemctl status etcd
---
#controller-0の出力
ubuntu@controller-0:~$ sudo systemctl daemon-reload
ubuntu@controller-0:~$ sudo systemctl enable etcd
Created symlink /etc/systemd/system/multi-user.target.wants/etcd.service → /etc/systemd/system/etcd.service.
ubuntu@controller-0:~$ sudo systemctl start etcd
ubuntu@controller-0:~$ sudo systemctl status etcd
● etcd.service - etcd
Loaded: loaded (/etc/systemd/system/etcd.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2025-10-20 22:33:49 UTC; 26s ago
Docs: https://github.cm/coreos
Main PID: 2285 (etcd)
Tasks: 8 (limit: 2218)
Memory: 12.8M
CPU: 433ms
CGroup: /system.slice/etcd.service
└─2285 /usr/local/bin/etcd --name controller-0 --cert-file=/etc/etcd/kubernetes.pem --key-file=/etc/e>
Oct 20 22:33:49 controller-0 etcd[2285]: {"level":"info","ts":"2025-10-20T22:33:49.03866Z","caller":"etcdserver/se>
Oct 20 22:33:49 controller-0 etcd[2285]: {"level":"info","ts":"2025-10-20T22:33:49.040276Z","caller":"embed/serve.>
Oct 20 22:33:49 controller-0 etcd[2285]: {"level":"info","ts":"2025-10-20T22:33:49.040356Z","caller":"etcdmain/mai>
Oct 20 22:33:49 controller-0 etcd[2285]: {"level":"info","ts":"2025-10-20T22:33:49.040454Z","caller":"etcdmain/mai>
Oct 20 22:33:49 controller-0 systemd[1]: Started etcd.
Oct 20 22:33:49 controller-0 etcd[2285]: {"level":"info","ts":"2025-10-20T22:33:49.046876Z","caller":"embed/serve.>
Oct 20 22:33:49 controller-0 etcd[2285]: {"level":"info","ts":"2025-10-20T22:33:49.054099Z","caller":"etcdserver/s>
Oct 20 22:33:49 controller-0 etcd[2285]: {"level":"info","ts":"2025-10-20T22:33:49.058485Z","caller":"membership/c>
Oct 20 22:33:49 controller-0 etcd[2285]: {"level":"info","ts":"2025-10-20T22:33:49.058665Z","caller":"api/capabili>
Oct 20 22:33:49 controller-0 etcd[2285]: {"level":"info","ts":"2025-10-20T22:33:49.058807Z","caller":"etcdserver/s>
ubuntu@controller-0:~$
- etcdクラスターの確認
sudo ETCDCTL_API=3 etcdctl member list \ --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/etcd/ca.pem \ --cert=/etc/etcd/kubernetes.pem \ --key=/etc/etcd/kubernetes-key.pem --- # controller-0の出力 ubuntu@controller-0:~$ sudo ETCDCTL_API=3 etcdctl member list \ --endpoints=https://127.0.0.1:2379 \ --cacert=/etc/etcd/ca.pem \ --cert=/etc/etcd/kubernetes.pem \ --key=/etc/etcd/kubernetes-key.pem 286ea08a76969776, started, controller-1, https://192.168.8.11:2380, https://192.168.8.11:2379, false 671e6154d5107277, started, controller-2, https://192.168.8.12:2380, https://192.168.8.12:2379, false 7e87d57c936a3019, started, controller-0, https://192.168.8.10:2380, https://192.168.8.10:2379, false ubuntu@controller-0:~$
Bootstrapping the Kubernetes Control Plane
概要
このステップでは、3つのcontrollerノードに以下のコンポーネントをインストールする:
1. kube-apiserver - Kubernetes APIのフロントエンド.
2. kube-controller-manager - クラスターの状態を管理.
3. kube-scheduler - Podの配置を決定.
4. RBACの設定.
5. nginxでkubeAPI用のロードバランサーを作成.
- 必要なファイルの配布
# controller-0への配布 scp ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \ service-account-key.pem service-account.pem \ encryption-config.yaml \ kube-controller-manager.kubeconfig \ kube-scheduler.kubeconfig \ ubuntu@192.168.8.10:~/ # controller-1への配布 scp ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \ service-account-key.pem service-account.pem \ encryption-config.yaml \ kube-controller-manager.kubeconfig \ kube-scheduler.kubeconfig \ ubuntu@192.168.8.11:~/ # controller-2への配布 scp ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \ service-account-key.pem service-account.pem \ encryption-config.yaml \ kube-controller-manager.kubeconfig \ kube-scheduler.kubeconfig \ ubuntu@192.168.8.12:~/ --- ubuntu@gateway-01:~/k8s-certs$ scp ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \ service-account-key.pem service-account.pem \ encryption-config.yaml \ kube-controller-manager.kubeconfig \ kube-scheduler.kubeconfig \ ubuntu@192.168.8.10:~/ ca.pem 100% 1306 1.6MB/s 00:00 ca-key.pem 100% 1675 3.4MB/s 00:00 kubernetes-key.pem 100% 1679 4.4MB/s 00:00 kubernetes.pem 100% 1659 4.7MB/s 00:00 service-account-key.pem 100% 1675 4.1MB/s 00:00 service-account.pem 100% 1428 4.0MB/s 00:00 encryption-config.yaml 100% 240 582.7KB/s 00:00 kube-controller-manager.kubeconfig 100% 6355 14.9MB/s 00:00 kube-scheduler.kubeconfig 100% 6305 13.9MB/s 00:00 ubuntu@gateway-01:~/k8s-certs$ scp ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \ service-account-key.pem service-account.pem \ encryption-config.yaml \ kube-controller-manager.kubeconfig \ kube-scheduler.kubeconfig \ ubuntu@192.168.8.11:~/ ca.pem 100% 1306 3.5MB/s 00:00 ca-key.pem 100% 1675 6.4MB/s 00:00 kubernetes-key.pem 100% 1679 6.2MB/s 00:00 kubernetes.pem 100% 1659 6.8MB/s 00:00 service-account-key.pem 100% 1675 8.2MB/s 00:00 service-account.pem 100% 1428 6.9MB/s 00:00 encryption-config.yaml 100% 240 1.3MB/s 00:00 kube-controller-manager.kubeconfig 100% 6355 24.7MB/s 00:00 kube-scheduler.kubeconfig 100% 6305 28.0MB/s 00:00 ubuntu@gateway-01:~/k8s-certs$ scp ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \ service-account-key.pem service-account.pem \ encryption-config.yaml \ kube-controller-manager.kubeconfig \ kube-scheduler.kubeconfig \ ubuntu@192.168.8.12:~/ ca.pem 100% 1306 3.6MB/s 00:00 ca-key.pem 100% 1675 6.5MB/s 00:00 kubernetes-key.pem 100% 1679 7.3MB/s 00:00 kubernetes.pem 100% 1659 7.9MB/s 00:00 service-account-key.pem 100% 1675 8.2MB/s 00:00 service-account.pem 100% 1428 7.2MB/s 00:00 encryption-config.yaml 100% 240 1.3MB/s 00:00 kube-controller-manager.kubeconfig 100% 6355 25.2MB/s 00:00 kube-scheduler.kubeconfig 100% 6305 28.1MB/s 00:00 ubuntu@gateway-01:~/k8s-certs$
- Kubernetesバイナリのダウンロードとインストール.
同期モードを有効化しておく. - Kubernetesバイナリのダウンロード.
sudo mkdir -p /etc/kubernetes/config # Kubernetes v1.29.1バイナリ wget -q --show-progress --https-only --timestamping \ "https://dl.k8s.io/v1.29.1/bin/linux/amd64/kube-apiserver" \ "https://dl.k8s.io/v1.29.1/bin/linux/amd64/kube-controller-manager" \ "https://dl.k8s.io/v1.29.1/bin/linux/amd64/kube-scheduler" \ "https://dl.k8s.io/v1.29.1/bin/linux/amd64/kubectl" --- # controller-0の出力 ubuntu@controller-0:~$ sudo mkdir -p /etc/kubernetes/config [sudo] password for ubuntu: ubuntu@controller-0:~$ ll /etc/kubernetes/config/ total 8 drwxr-xr-x 2 root root 4096 Oct 21 22:21 ./ drwxr-xr-x 3 root root 4096 Oct 21 22:21 ../ ubuntu@controller-0:~$ wget -q --show-progress --https-only --timestamping \ "https://dl.k8s.io/v1.29.1/bin/linux/amd64/kube-apiserver" \ "https://dl.k8s.io/v1.29.1/bin/linux/amd64/kube-controller-manager" \ "https://dl.k8s.io/v1.29.1/bin/linux/amd64/kube-scheduler" \ "https://dl.k8s.io/v1.29.1/bin/linux/amd64/kubectl" kube-apiserver 100%[=============================================>] 117.99M 3.11MB/s in 41s kube-controller-manager 100%[=============================================>] 112.87M 2.21MB/s in 42s kube-scheduler 100%[=============================================>] 53.35M 3.06MB/s in 19s kubectl 100%[=============================================>] 47.40M 5.32MB/s in 8.2s ubuntu@controller-0:~$
- バイナリのインストール
chmod +x kube-apiserver kube-controller-manager kube-scheduler kubectl sudo mv kube-apiserver kube-controller-manager kube-scheduler kubectl /usr/local/bin/ kubectl version --client --- # controller-0の出力 ubuntu@controller-0:~$ chmod +x kube-apiserver kube-controller-manager kube-scheduler kubectl ubuntu@controller-0:~$ sudo mv kube-apiserver kube-controller-manager kube-scheduler kubectl /usr/local/bin/ ubuntu@controller-0:~$ kubectl version --client Client Version: v1.29.1 Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3 ubuntu@controller-0:~$
- kube-apiserverの設定.
- 証明書と設定ファイルの配置.
sudo mkdir -p /var/lib/kubernetes/ sudo cp ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \ service-account-key.pem service-account.pem \ encryption-config.yaml /var/lib/kubernetes/ --- # controller-0の出力 ubuntu@controller-0:~$ sudo mkdir -p /var/lib/kubernetes/ ubuntu@controller-0:~$ sudo cp ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \ service-account-key.pem service-account.pem \ encryption-config.yaml /var/lib/kubernetes/ ubuntu@controller-0:~$ ll /var/lib/kubernetes/ total 36 drwxr-xr-x 2 root root 4096 Oct 21 22:37 ./ drwxr-xr-x 42 root root 4096 Oct 21 22:37 ../ -rw------- 1 root root 1675 Oct 21 22:37 ca-key.pem -rw-r--r-- 1 root root 1306 Oct 21 22:37 ca.pem -rw------- 1 root root 240 Oct 21 22:37 encryption-config.yaml -rw------- 1 root root 1679 Oct 21 22:37 kubernetes-key.pem -rw-r--r-- 1 root root 1659 Oct 21 22:37 kubernetes.pem -rw------- 1 root root 1675 Oct 21 22:37 service-account-key.pem -rw-r--r-- 1 root root 1428 Oct 21 22:37 service-account.pem ubuntu@controller-0:~$
- kube-apiserver systemdサービスファイルの作成.
- controller-0での作業.
INTERNAL_IP=192.168.8.10
cat <<EOF | sudo tee /etc/systemd/system/kube-apiserver.service
[Unit]
Description=Kubernetes API Server
Documentation=https://github.com/kubernetes/kubernetes
[Service]
ExecStart=/usr/local/bin/kube-apiserver \\
--advertise-address=${INTERNAL_IP} \\
--allow-privileged=true \\
--apiserver-count=3 \\
--audit-log-maxage=30 \\
--audit-log-maxbackup=3 \\
--audit-log-maxsize=100 \\
--audit-log-path=/var/log/audit.log \\
--authorization-mode=Node,RBAC \\
--bind-address=0.0.0.0 \\
--client-ca-file=/var/lib/kubernetes/ca.pem \\
--enable-admission-plugins=NamespaceLifecycle,NodeRestriction,LimitRanger,ServiceAccount,DefaultStorageClass,ResourceQuota \\
--etcd-cafile=/var/lib/kubernetes/ca.pem \\
--etcd-certfile=/var/lib/kubernetes/kubernetes.pem \\
--etcd-keyfile=/var/lib/kubernetes/kubernetes-key.pem \\
--etcd-servers=https://192.168.8.10:2379,https://192.168.8.11:2379,https://192.168.8.12:2379 \\
--event-ttl=1h \\
--encryption-provider-config=/var/lib/kubernetes/encryption-config.yaml \\
--kubelet-certificate-authority=/var/lib/kubernetes/ca.pem \\
--kubelet-client-certificate=/var/lib/kubernetes/kubernetes.pem \\
--kubelet-client-key=/var/lib/kubernetes/kubernetes-key.pem \\
--runtime-config='api/all=true' \\
--service-account-key-file=/var/lib/kubernetes/service-account.pem \\
--service-account-signing-key-file=/var/lib/kubernetes/service-account-key.pem \\
--service-account-issuer=https://${INTERNAL_IP}:6443 \\
--service-cluster-ip-range=10.32.0.0/24 \\
--service-node-port-range=30000-32767 \\
--tls-cert-file=/var/lib/kubernetes/kubernetes.pem \\
--tls-private-key-file=/var/lib/kubernetes/kubernetes-key.pem \\
--v=2
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
kube-controller-managerの設定.
同期モードを有効化しておく.kubeconfigの配置
sudo cp ~/kube-controller-manager.kubeconfig /var/lib/kubernetes/
- kube-controller-manager systemdサービスファイルの作成
cat <<EOF | sudo tee /etc/systemd/system/kube-controller-manager.service [Unit] Description=Kubernetes Controller Manager Documentation=https://github.com/kubernetes/kubernetes [Service] ExecStart=/usr/local/bin/kube-controller-manager \\ --bind-address=0.0.0.0 \\ --cluster-cidr=10.200.0.0/16 \\ --cluster-name=kubernetes \\ --cluster-signing-cert-file=/var/lib/kubernetes/ca.pem \\ --cluster-signing-key-file=/var/lib/kubernetes/ca-key.pem \\ --kubeconfig=/var/lib/kubernetes/kube-controller-manager.kubeconfig \\ --leader-elect=true \\ --root-ca-file=/var/lib/kubernetes/ca.pem \\ --service-account-private-key-file=/var/lib/kubernetes/service-account-key.pem \\ --service-cluster-ip-range=10.32.0.0/24 \\ --use-service-account-credentials=true \\ --v=2 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target EOF
重要なパラメータ .
--cluster-cidr=10.200.0.0/16: Pod用のIPレンジ.
--service-cluster-ip-range=10.32.0.0/24: Service用のIPレン.
--leader-elect=true: 高可用性のためのリーダー選出.
- kube-schedulerの設定.
- kubeconfigの配置.
sudo cp ~/kube-scheduler.kubeconfig /var/lib/kubernetes/
- kube-scheduler設定ファイルの作成
cat <<EOF | sudo tee /etc/kubernetes/config/kube-scheduler.yaml apiVersion: kubescheduler.config.k8s.io/v1 kind: KubeSchedulerConfiguration clinetConnection: kubeconfig: "/var/lib/kubernetes/kube-scheduler.kubeconfig" leaderElection: leaderElect: true EOF
- kube-scheduler systemdサービスファイルの作成
cat <<EOF | sudo tee /etc/systemd/system/kube-scheduler.service [Unit] Description=Kubernetes Scheduler Documentation=https://github.com/kubernetes/kubernetes [Service] ExecStart=/usr/local/bin/kube-scheduler \\ --config=/etc/kubernetes/config/kube-scheduler.yaml \\ --v=2 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target EOF
- Kubernetes Control Planeサービスの起動
sudo systemctl daemon-reload
sudo systemctl enable kube-apiserver kube-controller-manager kube-scheduler
sudo systemctl start kube-apiserver kube-controller-manager kube-scheduler
sleep 10
# サービスの状態確認
sudo systemctl status kube-apiserver --no-pager
sudo systemctl status kube-controller-manager --no-pager
sudo systemctl status kube-scheduler --no-pager
---
# controller-0の出力
ubuntu@controller-0:~$ sudo systemctl daemon-reload
ubuntu@controller-0:~$ sudo systemctl enable kube-apiserver kube-controller-manager kube-scheduler
Created symlink /etc/systemd/system/multi-user.target.wants/kube-apiserver.service → /etc/systemd/system/kube-apiserver.service.
Created symlink /etc/systemd/system/multi-user.target.wants/kube-controller-manager.service → /etc/systemd/system/kube-controller-manager.service.
Created symlink /etc/systemd/system/multi-user.target.wants/kube-scheduler.service → /etc/systemd/system/kube-scheduler.service.
ubuntu@controller-0:~$ sudo systemctl start kube-apiserver kube-controller-manager kube-scheduler
ubuntu@controller-0:~$ sleep 10
ubuntu@controller-0:~$ sudo systemctl status kube-apiserver --no-pager
● kube-apiserver.service - Kubernetes API Server
Loaded: loaded (/etc/systemd/system/kube-apiserver.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2025-10-22 22:43:11 UTC; 27s ago
Docs: https://github.com/kubernetes/kubernetes
Main PID: 17536 (kube-apiserver)
Tasks: 9 (limit: 2218)
Memory: 302.0M
CPU: 3.310s
CGroup: /system.slice/kube-apiserver.service
└─17536 /usr/local/bin/kube-apiserver --advertise-address=192.168.8.10 --allow-privileged=true --apis…
Oct 22 22:43:16 controller-0 kube-apiserver[17536]: [-]poststarthook/rbac/bootstrap-roles failed: not finished
Oct 22 22:43:16 controller-0 kube-apiserver[17536]: I1022 22:43:16.425237 17536 healthz.go:261] poststarth…readyz
Oct 22 22:43:16 controller-0 kube-apiserver[17536]: [-]poststarthook/rbac/bootstrap-roles failed: not finished
Oct 22 22:43:16 controller-0 kube-apiserver[17536]: I1022 22:43:16.492598 17536 controller.go:624] quota a…k8s.io
Oct 22 22:43:16 controller-0 kube-apiserver[17536]: I1022 22:43:16.524474 17536 healthz.go:261] poststarth…readyz
Oct 22 22:43:16 controller-0 kube-apiserver[17536]: [-]poststarthook/rbac/bootstrap-roles failed: not finished
Oct 22 22:43:16 controller-0 kube-apiserver[17536]: I1022 22:43:16.639181 17536 alloc.go:330] "allocated c….0.1"}
Oct 22 22:43:16 controller-0 kube-apiserver[17536]: W1022 22:43:16.674497 17536 lease.go:265] Resetting en….8.12]
Oct 22 22:43:16 controller-0 kube-apiserver[17536]: I1022 22:43:16.675441 17536 controller.go:624] quota a…points
Oct 22 22:43:16 controller-0 kube-apiserver[17536]: I1022 22:43:16.702904 17536 controller.go:624] quota a…k8s.io
Hint: Some lines were ellipsized, use -l to show in full.
ubuntu@controller-0:~$ sudo systemctl status kube-controller-manager --no-pager
● kube-controller-manager.service - Kubernetes Controller Manager
Loaded: loaded (/etc/systemd/system/kube-controller-manager.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2025-10-22 22:43:11 UTC; 34s ago
Docs: https://github.com/kubernetes/kubernetes
Main PID: 17537 (kube-controller)
Tasks: 5 (limit: 2218)
Memory: 87.1M
CPU: 531ms
CGroup: /system.slice/kube-controller-manager.service
└─17537 /usr/local/bin/kube-controller-manager --bind-address=0.0.0.0 --cluster-cidr=10.200.0.0/16 --…
Oct 22 22:43:12 controller-0 kube-controller-manager[17537]: W1022 22:43:12.245345 17537 authentication.go:…work.
Oct 22 22:43:12 controller-0 kube-controller-manager[17537]: W1022 22:43:12.245576 17537 authorization.go:1…work.
Oct 22 22:43:12 controller-0 kube-controller-manager[17537]: I1022 22:43:12.248029 17537 controllermanager.…29.1"
Oct 22 22:43:12 controller-0 kube-controller-manager[17537]: I1022 22:43:12.248191 17537 controllermanager.…CK=""
Oct 22 22:43:12 controller-0 kube-controller-manager[17537]: I1022 22:43:12.249957 17537 tlsconfig.go:200] "Load…
Oct 22 22:43:12 controller-0 kube-controller-manager[17537]: I1022 22:43:12.250459 17537 named_certificates.go:5…
Oct 22 22:43:12 controller-0 kube-controller-manager[17537]: I1022 22:43:12.250644 17537 secure_serving.go:…10257
Oct 22 22:43:12 controller-0 kube-controller-manager[17537]: I1022 22:43:12.250711 17537 tlsconfig.go:240] …ller"
Oct 22 22:43:12 controller-0 kube-controller-manager[17537]: I1022 22:43:12.253739 17537 leaderelection.go:…er...
Oct 22 22:43:13 controller-0 kube-controller-manager[17537]: E1022 22:43:13.856984 17537 leaderelection.go:332] …
Hint: Some lines were ellipsized, use -l to show in full.
ubuntu@controller-0:~$ sudo systemctl status kube-scheduler --no-pager
● kube-scheduler.service - Kubernetes Scheduler
Loaded: loaded (/etc/systemd/system/kube-scheduler.service; enabled; vendor preset: enabled)
Active: activating (auto-restart) (Result: exit-code) since Wed 2025-10-22 22:43:49 UTC; 194ms ago
Docs: https://github.com/kubernetes/kubernetes
Process: 17615 ExecStart=/usr/local/bin/kube-scheduler --config=/etc/kubernetes/config/kube-scheduler.yaml --v=2 (code=exited, status=1/FAILURE)
Main PID: 17615 (code=exited, status=1/FAILURE)
CPU: 300ms
ubuntu@controller-0:~$
controller-0とcontroller-2でkube-schedulerが動いていない。
ubuntu@controller-0:~$ sudo systemctl status kube-scheduler --no-pager
● kube-scheduler.service - Kubernetes Scheduler
Loaded: loaded (/etc/systemd/system/kube-scheduler.service; enabled; vendor preset: enabled)
Active: activating (auto-restart) (Result: exit-code) since Wed 2025-10-22 22:43:49 UTC; 194ms ago
Docs: https://github.com/kubernetes/kubernetes
Process: 17615 ExecStart=/usr/local/bin/kube-scheduler --config=/etc/kubernetes/config/kube-scheduler.yaml --v=2 (code=exited, status=1/FAILURE)
Main PID: 17615 (code=exited, status=1/FAILURE)
CPU: 300ms
ubuntu@controller-0:~$
---
ubuntu@controller-2:~$ sudo systemctl status kube-scheduler --no-pager
● kube-scheduler.service - Kubernetes Scheduler
Loaded: loaded (/etc/systemd/system/kube-scheduler.service; enabled; vendor preset: enabled)
Active: activating (auto-restart) (Result: exit-code) since Fri 2025-10-24 19:36:16 UTC; 1s ago
Docs: https://github.com/kubernetes/kubernetes
Process: 251006 ExecStart=/usr/local/bin/kube-scheduler --config=/etc/kubernetes/config/kube-scheduler.yaml --v=2 (code=exited, status=1/FAILURE)
Main PID: 251006 (code=exited, status=1/FAILURE)
CPU: 403ms
ubuntu@controller-2:~$
- エラーログ解析
controller-0の
jounalctlを見る
sudo journalctl -u kube-scheduler -n 50 --no-pager
コマンドが違いそう
ubuntu@controller-0:~$ sudo journalctl -u kube-scheduler -n 50 --no-pager [中略] Oct 24 19:39:16 controller-0 kube-scheduler[251632]: E1024 19:39:16.825427 251632 run.go:74] "command failed" err="strict decoding error: unknown field \"clinetConnection\"" Oct 24 19:39:16 controller-0 systemd[1]: kube-scheduler.service: Main process exited, code=exited, status=1/FAILURE Oct 24 19:39:16 controller-0 systemd[1]: kube-scheduler.service: Failed with result 'exit-code'. ubuntu@controller-0:~$
- 設定ファイルの確認
cat /etc/kubernetes/config/kube-scheduler.yaml
- 再度設定ファイルを作成.
同期モードにしておく.
cat <<EOF | sudo tee /etc/kubernetes/config/kube-scheduler.yaml apiVersion: kubescheduler.config.k8s.io/v1 kind: KubeSchedulerConfiguration clientConnection: kubeconfig: "/var/lib/kubernetes/kube-scheduler.kubeconfig" leaderElection: leaderElect: true EOF
- 再起動
sudo systemctl restart kube-scheduler sudo systemctl status kube-scheduler
全てactiveになった
- 動作確認.
同期モードを解除しておく.
# controller-0で確認
kubectl cluster-info --kubeconfig ~/admin.kubeconfig
# エラーの場合下記
sudo kubectl get componentstatuses --kubeconfig /var/lib/kubernetes/kube-controller-manager.kubeconfig
curl -k https://127.0.0.1:6443/version
---
ubuntu@controller-0:~$ sudo kubectl get componentstatuses --kubeconfig /var/lib/kubernetes/kube-controller-manager.kubeconfig
Warning: v1 ComponentStatus is deprecated in v1.19+
NAME STATUS MESSAGE ERROR
scheduler Healthy ok
etcd-0 Healthy ok
controller-manager Healthy ok
ubuntu@controller-0:~$ curl -k https://127.0.0.1:6443/version
{
"major": "1",
"minor": "29",
"gitVersion": "v1.29.1",
"gitCommit": "bc401b91f2782410b3fb3f9acf43a995c4de90d2",
"gitTreeState": "clean",
"buildDate": "2024-01-17T15:41:12Z",
"goVersion": "go1.21.6",
"compiler": "gc",
"platform": "linux/amd64"
}ubuntu@controller-0:~$
- RBAC for Kubelet Authorization.
kubelete APIへのアクセうを許可するRBAC設定を作成 controller-0で実施.
cat <<EOF | sudo kubectl apply --kubeconfig /var/lib/kubernetes/kube-controller-manager.kubeconfig -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:kube-apiserver-to-kubelet
rules:
- apiGroups:
- ""
resources:
- nodes/proxy
- nodes/stats
- nodes/log
- nodes/spec
- nodes/metrics
verbs:
- "*"
EOF
---
Error from server (Forbidden): error when retrieving current configuration of:
Resource: "rbac.authorization.k8s.io/v1, Resource=clusterroles", GroupVersionKind: "rbac.authorization.k8s.io/v1, Kind=ClusterRole"
Name: "system:kube-apiserver-to-kubelet", Namespace: ""
from server for: "STDIN": clusterroles.rbac.authorization.k8s.io "system:kube-apiserver-to-kubelet" is forbidden: User "system:kube-controller-manager" cannot get resource "clusterroles" in API group "rbac.authorization.k8s.io" at the cluster scope
ubuntu@controller-0:~$
- admin.kubeconfigをcontroller-0に配布.
gateway-01で実行.
scp admin.kubeconfig ubuntu@192.168.8.10:~/
~/admin.kubeconfigを実行
cat <<EOF | kubectl apply --kubeconfig ~/admin.kubeconfig -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:kube-apiserver-to-kubelet
rules:
- apiGroups:
- ""
resources:
- nodes/proxy
- nodes/stats
- nodes/log
- nodes/spec
- nodes/metrics
verbs:
- "*"
EOF
---
ubuntu@controller-0:~$ cat <<EOF | kubectl apply --kubeconfig ~/admin.kubeconfig -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:kube-apiserver-to-kubelet
rules:
- apiGroups:
EOF - "*"es/metrics
error: error validating "STDIN": error validating data: failed to download openapi: Get "https://192.168.3.18:6443/openapi/v2?timeout=32s": dial tcp 192.168.3.18:6443: connect: connection refused; if you choose to ignore these errors, turn validation off with --validate=false
ubuntu@controller-0:~$
gatewaty-01で実行
cd ~/k8s-certs
cat <<EOF | kubectl apply --kubeconfig admin.kubeconfig -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:kube-apiserver-to-kubelet
rules:
- apiGroups:
- ""
resources:
- nodes/proxy
- nodes/stats
- nodes/log
- nodes/spec
- nodes/metrics
verbs:
- "*"
EOF
---
ubuntu@gateway-01:~/k8s-certs$ cat <<EOF | kubectl apply --kubeconfig admin.kubeconfig -f - apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:kube-apiserver-to-kubelet
rules:
- apiGroups:
- ""
resources:
- nodes/proxy
- nodes/stats
- nodes/log
- nodes/spec
- nodes/metrics
verbs:
- "*"
EOF
error: error validating "STDIN": error validating data: failed to download openapi: Get "https://192.168.3.18:6443/openapi/v2?timeout=32s": dial tcp 192.168.3.18:6443: connect: connection refused; if you choose to ignore these errors, turn validation off with --validate=false
ubuntu@gateway-01:~/k8s-certs$
- HAProxy設定ファイルの作成
cat <<EOF | sudo tee /etc/haproxy/haproxy.cfg global log /dev/log local0 log /dev/log local1 notice chroot /var/lib/haproxy stats socket /run/haproxy/admin.sock mode 660 level admin stats timeout 30s user haproxy group haproxy daemon defaults log global mode http option httplog option dontlognull timeout connect 5000 timeout client 50000 timeout server 50000 frontend kubernetes-apiserver bind *:6443 mode tcp option tcplog default_backend kubernetes-apiserver backend kubernetes-apiserver mode tcp option tcp-check balance roundrobin server controller-0 192.168.8.10:6443 check fall 3 rise 2 server controller-1 192.168.8.11:6443 check fall 3 rise 2 server controller-2 192.168.8.12:6443 check fall 3 rise 2 EOF
実行の確認
ubuntu@gateway-01:~/k8s-certs$ sudo systemctl restart haproxy
ubuntu@gateway-01:~/k8s-certs$ sudo systemctl enable haproxy
Synchronizing state of haproxy.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable haproxy
ubuntu@gateway-01:~/k8s-certs$ sudo systemctl status haproxy
● haproxy.service - HAProxy Load Balancer
Loaded: loaded (/lib/systemd/system/haproxy.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2025-10-24 20:25:21 UTC; 7s ago
Docs: man:haproxy(1)
file:/usr/share/doc/haproxy/configuration.txt.gz
Main PID: 20213 (haproxy)
Tasks: 2 (limit: 2220)
Memory: 71.2M
CPU: 66ms
CGroup: /system.slice/haproxy.service
├─20213 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /run/haproxy-master.>
└─20215 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /run/haproxy-master.>
Oct 24 20:25:21 gateway-01 haproxy[20110]: [WARNING] (20110) : Exiting Master process...
Oct 24 20:25:21 gateway-01 haproxy[20110]: [NOTICE] (20110) : haproxy version is 2.4.24-0ubuntu0.22.04.3
Oct 24 20:25:21 gateway-01 haproxy[20110]: [NOTICE] (20110) : path to executable is /usr/sbin/haproxy
Oct 24 20:25:21 gateway-01 haproxy[20110]: [ALERT] (20110) : Current worker #1 (20112) exited with code 143 (Te>
Oct 24 20:25:21 gateway-01 haproxy[20110]: [WARNING] (20110) : All workers exited. Exiting... (0)
Oct 24 20:25:21 gateway-01 systemd[1]: haproxy.service: Deactivated successfully.
Oct 24 20:25:21 gateway-01 systemd[1]: Stopped HAProxy Load Balancer.
Oct 24 20:25:21 gateway-01 systemd[1]: Starting HAProxy Load Balancer...
Oct 24 20:25:21 gateway-01 haproxy[20213]: [NOTICE] (20213) : New worker #1 (20215) forked
Oct 24 20:25:21 gateway-01 systemd[1]: Started HAProxy Load Balancer.
lines 1-23/23 (END)
ubuntu@gateway-01:~/k8s-certs$
ClusterRole設定できた
}ubuntu@gateway-01:~/k8s-certs$cat <<EOF | kubectl apply --kubeconfig admin.kubeconfig -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:kube-apiserver-to-kubelet
rules:
- apiGroups:
- ""
resources:
- nodes/proxy
- nodes/stats
- nodes/log
- nodes/spec
- nodes/metrics
verbs:
- "*"
EOF
clusterrole.rbac.authorization.k8s.io/system:kube-apiserver-to-kubelet created
ubuntu@gateway-01:~/k8s-certs$
ClusterRoleBindingの作成
cat <<EOF | kubectl apply --kubeconfig admin.kubeconfig -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:kube-apiserver
namespace: ""
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:kube-apiserver-to-kubelet
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: User
name: kubernetes
EOF
リソース確認
ubuntu@gateway-01:~/k8s-certs$ kubectl get clusterrole system:kube-apiserver-to-kubelet --kubeconfig admin.kubeconfig NAME CREATED AT system:kube-apiserver-to-kubelet 2025-10-24T20:32:56Z ubuntu@gateway-01:~/k8s-certs$ kubectl get clusterrolebinding system:kube-apiserver --kubeconfig admin.kubeconfig NAME ROLE AGE system:kube-apiserver ClusterRole/system:kube-apiserver-to-kubelet 48s ubuntu@gateway-01:~/k8s-certs$
- gateway-01でのHTTPヘルスチェック設定
- CA証明書の配置.
sudo mkdir -p /var/lib/kubernetes sudo cp ca.pem /var/lib/kubernetes
- nginxのインストール
sudo apt update sudo apt install -y nginx
- nginx設定ファイルの作成
cat <<EOF | sudo tee /etc/nginx/sites-available/kubernetes.default.svc.cluster.local
server {
listen 80;
server_name kubernetes.default.svc.cluster.local;
location /healthz {
proxy_pass https://127.0.0.1:6443/healthz;
proxy_ssl_trusted_certificate /var/lib/kubernetes/ca.pem;
}
}
EOF
- シンボリックリンクの作成
sudo ln -sf /etc/nginx/sites-available/kubernetes.default.svc.cluster.local /etc/nginx/sites-enabled/
- nginxの再起動
sudo nginx -t # 設定テスト sudo systemctl restart nginx sudo systemctl enable nginx --- ubuntu@gateway-01:~/k8s-certs$ sudo nginx -t # 設定テスト nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful ubuntu@gateway-01:~/k8s-certs$ sudo systemctl restart nginx ubuntu@gateway-01:~/k8s-certs$ sudo systemctl enable nginx Synchronizing state of nginx.service with SysV service script with /lib/systemd/systemd-sysv-install. Executing: /lib/systemd/systemd-sysv-install enable nginx ubuntu@gateway-01:~/k8s-certs$
curl -H "Host: kubernetes.default.svc.cluster.local" http://127.0.0.1/healthz --- ubuntu@gateway-01:~/k8s-certs$ curl -H "Host: kubernetes.default.svc.cluster.local" http://127.0.0.1/healthz okubuntu@gateway-01:~/k8s-certs$
Bootstrapping the Kubernetes Worker Nodes
概要
このステップでは、3つのworkerノードに以下をインストールする:
1. 依存パッケージ(socat, conntrack, ipset).
2. containerd(コンテナランタイム).
3. CNIプラグイン(ネットワーク).
4. kubelet(Podの管理).
5. kube-proxy(ネットワークプロキシ).
- 証明書とkubeconfigの配布
#worker-0 scp cap.pem worker-0-key.pem worker-0.pem \ worker-0.kubeconfig kube-proxy.kubeconfig \ ubuntu@192.168.8.20:~/ #worker-1 scp cap.pem worker-1-key.pem worker-1.pem \ worker-1.kubeconfig kube-proxy.kubeconfig \ ubuntu@192.168.8.21:~/ #worker-2 scp cap.pem worker-2-key.pem worker-2.pem \ worker-2.kubeconfig kube-proxy.kubeconfig \ ubuntu@192.168.8.22:~/
workerノードを3つのペインに分割する.
同期モードを有効化しておく.
- 依存パッケージのインストール
sudo apt update sudo apt install -y socat conntrack ipset
- swapの無効化確認
sudo swapon --show free -h
- ディレクトリの作成
sudo mkdir -p \ /etc/cni/net.d \ /opt/cni/bin \ /var/lib/kubelet \ /var/lib/kube-proxy \ /var/lib/kubernetes \ /var/run/kubernetes
ディレクトリの説明:
- /etc/cni/net.d: CNI設定ファイル.
- /opt/cni/bin: CNIプラグインバイナリ.
- /var/lib/kubelet: kubelet用データ.
- /var/lib/kube-proxy: kube-proxy用データ.
- バイナリのダウンロードとインストール.
containerd、CNIプラグイン、kubelet、kube-proxyのダウンロード
wget -q --show-progress --https-only --timestamping \ https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.29.0/crictl-v1.29.0-linux-amd64.tar.gz \ https://github.com/opencontainers/runc/releases/download/v1.1.12/runc.amd64 \ https://github.com/containernetworking/plugins/releases/download/v1.4.0/cni-plugins-linux-amd64-v1.4.0.tgz \ https://github.com/containerd/containerd/releases/download/v1.7.13/containerd-1.7.13-linux-amd64.tar.gz \ https://dl.k8s.io/v1.29.1/bin/linux/amd64/kubectl \ https://dl.k8s.io/v1.29.1/bin/linux/amd64/kube-proxy \ https://dl.k8s.io/v1.29.1/bin/linux/amd64/kubelet
- ディレクトリの作成.
- バイナリのインストール.
sudo mkdir -p /etc/containerd sudo mv runc.amd64 runc chmod +x runc kubectl kube-proxy kubelet sudo mv runc kubectl kube-proxy kubelet /usr/local/bin/ sudo tar -xvf cni-plugins-linux-amd64-v1.4.0.tgz -C /opt/cni/bin/ sudo tar -xvf containerd-1.7.13-linux-amd64.tar.gz -C /usr/local/aws-cli/ tar -xvf crictl-v1.29.0-linux-amd64.tar.gz sudo mv crictl /usr/local/bin/
CNIネットワークの設定.
同期モードを解除しておく.worker-0
POD_CIDR=10.200.0.0/24
cat <<EOF | sudo tee /etc/cni/net.d/10-bridge.conf
{
"cniVersion": "1.0.0",
"name": "bridge",
"type": "bridge",
"bridge": "cnio0",
"isGateway": true,
"ipMasq": true,
"ipam": {
"type": "host-local",
"ranges": [
[{"subnet": "${POD_CIDR}"}]
],
"routes": [{"dst": "0.0.0.0/0"}]
}
}
EOF
- loopback設定(全worker共通)
cat <<EOF | sudo tee /etc/cni/net.d/99-loopback.conf
{
"cniVersion": "1.0.0",
"name": "lo",
"type": "loopback"
}
EOF
containerdの設定.
同期モードを有効化しておく.containerd設定ファイルの作成
cat <<EOF | sudo tee /etc/containerd/config.toml
version = 2
[plugins]
[plugins."io.containerd.grpc.v1.cri"]
[plugins."io.containerd.grpc.v1.cri".containerd]
snapshotter = "overlayfs"
[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
EOF
- containerd systemdサービスファイルの作成
cat <<EOF | sudo tee /etc/systemd/system/containerd.service [Unit] Description=containerd container runtime Documentation=https://containerd.io After=network.target [Service] ExecStartPre=/sbin/modprobe overlay ExecStart=/usr/local/bin/containerd Restart=always RestartSec=5 Delegate=yes KillMode=process OOMScoreAdjust=-999 LimitNOFILE=1048576 LimitNPROC=infinity LimitCORE=infinity [Install] WantedBy=multi-user.target EOF
kubeletの設定. 同期モードを解除しておく.
worker-0での設定
sudo cp ~/worker-0-key.pem ~/worker-0.pem /var/lib/kubelet/
sudo cp ~/worker-0.kubeconfig /var/lib/kubelet/kubeconfig
sudo cp ~/ca.pem /var/lib/kubernetes/
# kubelet設定ファイルの作成
cat <<EOF | sudo tee /var/lib/kubelet/kubelet-config.yaml
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
anonymous:
enabled: false
webhook:
enabled: true
x509:
clientCAFile: "/var/lib/kubernetes/ca.pem"
authorization:
mode: Webhook
clusterDomain: "cluster.local"
clusterDNS:
- "10.32.0.10"
podCIDR: "10.200.0.0/24"
resolvConf: "/run/systemd/resolve/resolv.conf"
runtimeRequestTimeout: "15m"
tlsCertFile: "/var/lib/kubelet/worker-0.pem"
tlsPrivateKeyFile: "/var/lib/kubelet/worker-0-key.pem"
EOF
- kubelet systemdサービスファイルの作成
cat <<EOF | sudo tee /etc/systemd/system/kubelet.service [Unit] Description=Kubernetes Kubelet Documentation=https://github.com/kubernetes/kubernetes After=containerd.service Requires=containerd.service [Service] ExecStart=/usr/local/bin/kubelet \\ --config=/var/lib/kubelet/kubelet-config.yaml \\ --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock \\ --kubeconfig=/var/lib/kubelet/kubeconfig \\ --v=2 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target EOF
- kube-proxyの設定.
- kube-proxy kubeconfigの配置.
sudo cp ~/kube-proxy.kubeconfig /var/lib/kube-proxy/kubeconfig
- kube-proxy設定ファイルの作成
cat <<EOF | sudo tee /var/lib/kube-proxy/kube-proxy-config.yaml kind: KubeProxyConfiguration apiVersion: kubeproxy.config.k8s.io/v1alpha1 clientConnection: kubeconfig: "/var/lib/kube-proxy/kubeconfig" mode: "iptables" clusterCIDR: "10.200.0.0/16" EOF
設定の説明:
- mode: "iptables": iptablesモードを使用(デフォルト).
- clusterCIDR: 全Podの IPレンジ(10.200.0.0/16).
- kube-proxy systemdサービスファイルの作成.
cat <<EOF | sudo tee /etc/systemd/system/kube-proxy.service [Unit] Description=Kubernetes Kube Proxy Documentation=https://github.com/kubernetes/kubernetes [Service] ExecStart=/usr/local/bin/kube-proxy \\ --config=/var/lib/kube-proxy/kube-proxy-config.yaml Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target EOF
- サービスの起動
sudo systemctl daemon-reload sudo systemctl enable containerd kubelet kube-proxy sudo systemctl start containerd kubelet kube-proxy
- サービスの状態確認
sudo systemctl status containerd --no-pager
sudo systemctl status kubelet --no-pager
sudo systemctl status kube-proxy --no-pager
---
ubuntu@worker-0:~$ sudo systemctl status containerd --no-pager
● containerd.service - containerd container runtime
Loaded: loaded (/etc/systemd/system/containerd.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2025-10-25 05:19:53 UTC; 2min 14s ago
Docs: https://containerd.io
Process: 20802 ExecStartPre=/sbin/modprobe overlay (code=exited, status=0/SUCCESS)
Main PID: 20807 (containerd)
Tasks: 8 (limit: 4555)
Memory: 16.5M
CPU: 250ms
CGroup: /system.slice/containerd.service
└─20807 /usr/local/bin/containerd
Oct 25 05:19:53 worker-0 containerd[20807]: time="2025-10-25T05:19:53.485675164Z" level=info msg="skipping …plugin"
Oct 25 05:19:53 worker-0 containerd[20807]: time="2025-10-25T05:19:53.486020448Z" level=info msg="Start sub… event"
Oct 25 05:19:53 worker-0 containerd[20807]: time="2025-10-25T05:19:53.486087043Z" level=info msg="Start rec… state"
Oct 25 05:19:53 worker-0 containerd[20807]: time="2025-10-25T05:19:53.486163629Z" level=info msg="Start eve…onitor"
Oct 25 05:19:53 worker-0 containerd[20807]: time="2025-10-25T05:19:53.486179639Z" level=info msg="Start sna…syncer"
Oct 25 05:19:53 worker-0 containerd[20807]: time="2025-10-25T05:19:53.486187694Z" level=info msg="Start cni…efault"
Oct 25 05:19:53 worker-0 containerd[20807]: time="2025-10-25T05:19:53.486196431Z" level=info msg="Start str…server"
Oct 25 05:19:53 worker-0 containerd[20807]: time="2025-10-25T05:19:53.486435935Z" level=info msg=serving...…k.ttrpc
Oct 25 05:19:53 worker-0 containerd[20807]: time="2025-10-25T05:19:53.486516688Z" level=info msg=serving...…rd.sock
Oct 25 05:19:53 worker-0 containerd[20807]: time="2025-10-25T05:19:53.486542227Z" level=info msg="container…56411s"
Hint: Some lines were ellipsized, use -l to show in full.
ubuntu@worker-0:~$ sudo systemctl status kubelet --no-pager
● kubelet.service - Kubernetes Kubelet
Loaded: loaded (/etc/systemd/system/kubelet.service; enabled; vendor preset: enabled)
Active: activating (auto-restart) (Result: exit-code) since Sat 2025-10-25 05:22:15 UTC; 1s ago
Docs: https://github.com/kubernetes/kubernetes
Process: 21179 ExecStart=/usr/local/bin/kubelet --config=/var/lib/kubelet/kubelet-config.yaml --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock --kubeconfig=/var/lib/kubelet/kubeconfig --v=2 (code=exited, status=1/FAILURE)
Main PID: 21179 (code=exited, status=1/FAILURE)
CPU: 64ms
ubuntu@worker-0:~$ sudo systemctl status kube-proxy --no-pager
● kube-proxy.service - Kubernetes Kube Proxy
Loaded: loaded (/etc/systemd/system/kube-proxy.service; enabled; vendor preset: enabled)
Active: activating (auto-restart) (Result: exit-code) since Sat 2025-10-25 05:22:25 UTC; 3s ago
Docs: https://github.com/kubernetes/kubernetes
Process: 21208 ExecStart=/usr/local/bin/kube-proxy --config=/var/lib/kube-proxy/kube-proxy-config.yaml (code=exited, status=1/FAILURE)
Main PID: 21208 (code=exited, status=1/FAILURE)
CPU: 37ms
ubuntu@worker-0:~$
エラーが発生したのでkubeletとkube-proxyのログをみる
sudo journalctl -u kubelet -n 50 --no-pager | tail -30 sudo journalctl -u kube-proxy -n 50 --no-pager | tail -30 --- ubuntu@worker-0:~$ sudo journalctl -u kubelet -n 50 --no-pager | tail -30 sudo journalctl -u kube-proxy -n 50 --no-pager | tail -30 [中略] Oct 25 06:24:22 worker-0 kubelet[30795]: E1025 06:24:22.098220 30795 run.go:74] "command failed" err="failed to run Kubelet: running with swap on is not supported, please disable swap! or set --fail-swap-on flag to false. /proc/swaps contained: [Filename\t\t\t\tType\t\tSize\t\tUsed\t\tPriority /swap.img file\t\t1867772\t\t0\t\t-2]" Oct 25 06:24:22 worker-0 systemd[1]: kubelet.service: Main process exited, code=exited, status=1/FAILURE Oct 25 06:24:22 worker-0 systemd[1]: kubelet.service: Failed with result 'exit-code'. Oct 25 06:24:01 worker-0 systemd[1]: kube-proxy.service: Main process exited, code=exited, status=1/FAILURE Oct 25 06:24:01 worker-0 systemd[1]: kube-proxy.service: Failed with result 'exit-code'. Oct 25 06:24:06 worker-0 systemd[1]: kube-proxy.service: Scheduled restart job, restart counter is at 734. Oct 25 06:24:06 worker-0 systemd[1]: Stopped Kubernetes Kube Proxy. Oct 25 06:24:06 worker-0 systemd[1]: Started Kubernetes Kube Proxy. Oct 25 06:24:06 worker-0 kube-proxy[30752]: E1025 06:24:06.298494 30752 server.go:556] "Error running ProxyServer" err="stat /var/lib/kube-proxy/kubeconfig: no such file or directory" Oct 25 06:24:06 worker-0 kube-proxy[30752]: E1025 06:24:06.299567 30752 run.go:74] "command failed" err="stat /var/lib/kube-proxy/kubeconfig: no such file or directory" Oct 25 06:24:06 worker-0 systemd[1]: kube-proxy.service: Main process exited, code=exited, status=1/FAILURE Oct 25 06:24:06 worker-0 systemd[1]: kube-proxy.service: Failed with result 'exit-code'. Oct 25 06:24:11 worker-0 systemd[1]: kube-proxy.service: Scheduled restart job, restart counter is at 735. Oct 25 06:24:11 worker-0 systemd[1]: Stopped Kubernetes Kube Proxy. Oct 25 06:24:11 worker-0 systemd[1]: Started Kubernetes Kube Proxy. Oct 25 06:24:11 worker-0 kube-proxy[30766]: E1025 06:24:11.552057 30766 server.go:556] "Error running ProxyServer" err="stat /var/lib/kube-proxy/kubeconfig: no such file or directory" Oct 25 06:24:11 worker-0 kube-proxy[30766]: E1025 06:24:11.552522 30766 run.go:74] "command failed" err="stat /var/lib/kube-proxy/kubeconfig: no such file or directory" Oct 25 06:24:11 worker-0 systemd[1]: kube-proxy.service: Main process exited, code=exited, status=1/FAILURE Oct 25 06:24:11 worker-0 systemd[1]: kube-proxy.service: Failed with result 'exit-code'. Oct 25 06:24:16 worker-0 systemd[1]: kube-proxy.service: Scheduled restart job, restart counter is at 736. Oct 25 06:24:16 worker-0 systemd[1]: Stopped Kubernetes Kube Proxy. Oct 25 06:24:16 worker-0 systemd[1]: Started Kubernetes Kube Proxy. Oct 25 06:24:16 worker-0 kube-proxy[30780]: E1025 06:24:16.807890 30780 server.go:556] "Error running ProxyServer" err="stat /var/lib/kube-proxy/kubeconfig: no such file or directory" Oct 25 06:24:16 worker-0 kube-proxy[30780]: E1025 06:24:16.808560 30780 run.go:74] "command failed" err="stat /var/lib/kube-proxy/kubeconfig: no such file or directory" Oct 25 06:24:16 worker-0 systemd[1]: kube-proxy.service: Main process exited, code=exited, status=1/FAILURE Oct 25 06:24:16 worker-0 systemd[1]: kube-proxy.service: Failed with result 'exit-code'. Oct 25 06:24:22 worker-0 systemd[1]: kube-proxy.service: Scheduled restart job, restart counter is at 737. Oct 25 06:24:22 worker-0 systemd[1]: Stopped Kubernetes Kube Proxy. Oct 25 06:24:22 worker-0 systemd[1]: Started Kubernetes Kube Proxy. Oct 25 06:24:22 worker-0 kube-proxy[30794]: E1025 06:24:22.052981 30794 server.go:556] "Error running ProxyServer" err="stat /var/lib/kube-proxy/kubeconfig: no such file or directory" Oct 25 06:24:22 worker-0 kube-proxy[30794]: E1025 06:24:22.053426 30794 run.go:74] "command failed" err="stat /var/lib/kube-proxy/kubeconfig: no such file or directory" Oct 25 06:24:22 worker-0 systemd[1]: kube-proxy.service: Main process exited, code=exited, status=1/FAILURE Oct 25 06:24:22 worker-0 systemd[1]: kube-proxy.service: Failed with result 'exit-code'. ubuntu@worker-0:~$
- 問題1: swapが有効になっている(kubelet).
- 問題2: kube-proxy kubeconfigが存在しない.
解決方法
- swapを無効化
sudo swapoff -a sudo sed -i '/swap/d' /etc/fstab sudo rm -f /swap.img free -h sudo swapon --show
- kube-proxy kubeconfigの配置確認
ls -l ~/kube-proxy.kubeconfig sudo cp ~/kube-proxy.kubeconfig /var/lib/kube-proxy/kubeconfig sudo ls -l /var/lib/kube-proxy/kubeconfig
- サービスの再起動
sudo systemctl restart kubelet kube-proxy sudo systemctl status kubelet --no-pager sudo systemctl status kube-proxy --no-pager
gateway-01でノードの登録を確認
kubectl get nodes --kubeconfig ~/k8s-certs/admin.kuberconfig --- ubuntu@gateway-01:~/k8s-certs$ kubectl get nodes --kubeconfig ~/k8s-certs/admin.kubeconfig NAME STATUS ROLES AGE VERSION worker-0 Ready <none> 5m3s v1.29.1 worker-1 Ready <none> 4m42s v1.29.1 worker-2 Ready <none> 4m42s v1.29.1 ubuntu@gateway-01:~/k8s-certs$
Configuring kubectl for Remote Access
概要
このステップでは、ローカルPCからKubernetesクラスターを操作できるようにkubectlを設定する。
現在、admin.kubeconfigはgateway-01に存在するが、これを:
- ローカルPCにコピー.
- kubectlで使用できるように設定.
kubectlはローカルPCにインストールしているのでローカルPCで実施した。
- admin.kubeconfigをローカルPCにコピー.
# ~/.kubeはすでに作成している scp ubuntu@192.168.3.18:~/k8s-certs/admin.kubeconfig ~/.kube/config chmod 600 ~/.kube/config
- 接続確認.
# クラスター情報の確認 kubectl cluster-info # ノード一覧の確認 kubectl get nodes # コンポーネントの状態確認 kubectl get componentstatuses # 全リソースの確認 kubectl get all --all-namespaces --- on ☸ admin on kubernetes-the-hard-way in default () memo-cho on master [!?] ♥ ❯ kubectl cluster-info Kubernetes control plane is running at https://192.168.3.18:6443 To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. on ☸ admin on kubernetes-the-hard-way in default () memo-cho on master [!?] ♥ ❯ kubectl get nodes NAME STATUS ROLES AGE VERSION worker-0 Ready <none> 15m v1.29.1 worker-1 Ready <none> 15m v1.29.1 worker-2 Ready <none> 15m v1.29.1 on ☸ admin on kubernetes-the-hard-way in default () memo-cho on master [!?] ♥ ❯ kubectl get componentstatuses Warning: v1 ComponentStatus is deprecated in v1.19+ NAME STATUS MESSAGE ERROR scheduler Healthy ok etcd-0 Healthy ok controller-manager Healthy ok on ☸ admin on kubernetes-the-hard-way in default () memo-cho on master [!?] ♥ ❯ kubectl get all --all-namespaces NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE default service/kubernetes ClusterIP 10.32.0.1 <none> 443/TCP 2d8h on ☸ admin on kubernetes-the-hard-way in default () memo-cho on master [!?] ♥
3.kubeconfigの内容確認.
# 設定の確認 kubectl config view # 現在のコンテキスト確認 kubectl config current-context # クラスター一覧 kubectl config get-clusters # ユーザー一覧 kubectl config get-users
Provisioning Pod Network Routes
概要
現在、各workerノードのPodは自分のノード内でしか通信できない。
異なるworkerノード間のPod通信を可能にするため、gateway-01にルーティング設定を追加する。
- Pod CIDRの割り当て
| Worker Node | Pod CIDR | IPレンジ |
|---|---|---|
| worker-0 | 10.200.0.0/24 | 10.200.0.1 ~ 10.200.0.254 |
| worker-1 | 10.200.1.0/24 | 10.200.1.1 ~ 10.200.1.254 |
| worker-2 | 10.200.2.0/24 | 10.200.2.1 ~ 10.200.2.254 |
- gateway-01でのルーティング設定.
- ルーティングテーブルの追加.
# worker-0へのルート sudo ip route add 10.200.0.0/24 via 192.168.8.20 # worker-1へのルート sudo ip route add 10.200.1.0/24 via 192.168.8.21 # worker-2へのルート sudo ip route add 10.200.2.0/24 via 192.168.8.22
- ルーティングテーブルの確認
ip route | grep "10.200" --- ubuntu@gateway-01:~$ ip route | grep "10.200" 10.200.0.0/24 via 192.168.8.20 dev ens19 10.200.1.0/24 via 192.168.8.21 dev ens19 10.200.2.0/24 via 192.168.8.22 dev ens19 ubuntu@gateway-01:~$
- ルートの永続化.
- Netplan設定ファイルの編集.
sudo vim /etc/netplan/01-netcfg.yaml
cat結果
ubuntu@gateway-01:~$ cat /etc/netplan/01-netcfg.yaml
network:
version: 2
ethernets:
ens18:
dhcp4: true
dhcp4-overrides:
route-metric: 100
ens19:
addresses:
- 192.168.8.1/24
dhcp4: false
routes:
- to: 10.200.0.0/24
via: 192.168.8.20
- to: 10.200.1.0/24
via: 192.168.8.21
- to: 10.200.2.0/24
via: 192.168.8.22
ubuntu@gateway-01:~$
- 設定の適用、再度確認
sudo netplan apply ip route | grep "10.200" --- ubuntu@gateway-01:~$ sudo netplan apply ** (generate:22253): WARNING **: 10:46:01.329: Permissions for /etc/netplan/01-netcfg.yaml are too open. Netplan configuration should NOT be accessible by others. WARNING:root:Cannot call Open vSwitch: ovsdb-server.service is not running. ** (process:22251): WARNING **: 10:46:01.647: Permissions for /etc/netplan/01-netcfg.yaml are too open. Netplan configuration should NOT be accessible by others. ** (process:22251): WARNING **: 10:46:01.775: Permissions for /etc/netplan/01-netcfg.yaml are too open. Netplan configuration should NOT be accessible by others. ** (process:22251): WARNING **: 10:46:01.775: Permissions for /etc/netplan/01-netcfg.yaml are too open. Netplan configuration should NOT be accessible by others. ubuntu@gateway-01:~$ ip route | grep "10.200" 10.200.0.0/24 via 192.168.8.20 dev ens19 proto static 10.200.1.0/24 via 192.168.8.21 dev ens19 proto static 10.200.2.0/24 via 192.168.8.22 dev ens19 proto static ubuntu@gateway-01:~$
- IP Forwardingの確認
# IP Forwardingが有効か確認 cat /proc/sys/net/ipv4/ip_forward --- ubuntu@gateway-01:~$ cat /proc/sys/net/ipv4/ip_forward 1 ubuntu@gateway-01:~$
ステップ12: Deploying the DNS Cluster Add-on
概要
CoreDNSマニフェストを作成する。
CoreDNSは、Kubernetesクラスター内のDNSサーバーです。これにより:
- ServiceをDNS名で参照できる(例: nginx.default.svc.cluster.local).
- Pod間の名前解決が可能になる.
- 外部DNSへのクエリも転送される.
- CoreDNSマニフェストの作成
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
name: coredns
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:coredns
rules:
- apiGroups:
- ""
resources:
- endpoints
- services
- pods
- namespaces
verbs:
- list
- watch
- apiGroups:
- discovery.k8s.io
resources:
- endpointslices
verbs:
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:coredns
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:coredns
subjects:
- kind: ServiceAccount
name: coredns
namespace: kube-system
---
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health {
lameduck 5s
}
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough in-addr.arpa ip6.arpa
ttl 30
}
prometheus :9153
forward . /etc/resolv.conf {
max_concurrent 1000
}
cache 30
loop
reload
loadbalance
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: coredns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/name: "CoreDNS"
spec:
replicas: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
selector:
matchLabels:
k8s-app: kube-dns
template:
metadata:
labels:
k8s-app: kube-dns
spec:
priorityClassName: system-cluster-critical
serviceAccountName: coredns
tolerations:
- key: "CriticalAddonsOnly"
operator: "Exists"
nodeSelector:
kubernetes.io/os: linux
containers:
- name: coredns
image: coredns/coredns:1.11.1
imagePullPolicy: IfNotPresent
resources:
limits:
memory: 170Mi
requests:
cpu: 100m
memory: 70Mi
args: [ "-conf", "/etc/coredns/Corefile" ]
volumeMounts:
- name: config-volume
mountPath: /etc/coredns
readOnly: true
ports:
- containerPort: 53
name: dns
protocol: UDP
- containerPort: 53
name: dns-tcp
protocol: TCP
- containerPort: 9153
name: metrics
protocol: TCP
securityContext:
allowPrivilegeEscalation: false
capabilities:
add:
- NET_BIND_SERVICE
drop:
- all
readOnlyRootFilesystem: true
livenessProbe:
httpGet:
path: /health
port: 8080
scheme: HTTP
initialDelaySeconds: 60
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 5
readinessProbe:
httpGet:
path: /ready
port: 8181
scheme: HTTP
dnsPolicy: Default
volumes:
- name: config-volume
configMap:
name: coredns
items:
- key: Corefile
path: Corefile
---
apiVersion: v1
kind: Service
metadata:
name: kube-dns
namespace: kube-system
annotations:
prometheus.io/port: "9153"
prometheus.io/scrape: "true"
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
kubernetes.io/name: "CoreDNS"
spec:
selector:
k8s-app: kube-dns
clusterIP: 10.32.0.10
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP
- name: metrics
port: 9153
protocol: TCP
EOF
---
serviceaccount/coredns created
clusterrole.rbac.authorization.k8s.io/system:coredns created
clusterrolebinding.rbac.authorization.k8s.io/system:coredns created
configmap/coredns created
deployment.apps/coredns created
service/kube-dns created
on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?⇣]
♥
重要: clusterIP: 10.32.0.10 はkubelet設定の clusterDNS と一致させる必要があります。
- デプロイの確認 pod,service,deploymentの確認
on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?⇣] ♥ ❯ k get pods -n kube-system -l k8s-app=kube-dns NAME READY STATUS RESTARTS AGE coredns-6d84d9c4b7-bnh7d 1/1 Running 0 42s coredns-6d84d9c4b7-tzg6w 1/1 Running 0 42s on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?⇣] ♥ ❯ k get service -n kube-system kube-dns NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kube-dns ClusterIP 10.32.0.10 <none> 53/UDP,53/TCP,9153/TCP 61s on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?⇣] ♥ ❯ k get deployment -n kube-system coredns NAME READY UP-TO-DATE AVAILABLE AGE coredns 2/2 2 2 84s on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?⇣] ♥
on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?⇣] ♥ ❯ k run busybox --image=busybox:1.28 --command -- sleep 3600 pod/busybox created on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?⇣] ❯ k get pods busybox NAME READY STATUS RESTARTS AGE busybox 1/1 Running 0 37s on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?⇣] ♥ ❯ k exec busybox -- nslookup kubernetes Server: 10.32.0.10 Address 1: 10.32.0.10 kube-dns.kube-system.svc.cluster.local Name: kubernetes Address 1: 10.32.0.1 kubernetes.default.svc.cluster.local on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?⇣] ♥ ❯ k exec busybox -- nslookup kube-dns.kube-system.svc.cluster.local Server: 10.32.0.10 Address 1: 10.32.0.10 kube-dns.kube-system.svc.cluster.local Name: kube-dns.kube-system.svc.cluster.local Address 1: 10.32.0.10 kube-dns.kube-system.svc.cluster.local on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?⇣] ♥
Smoke Test
テスト項目
- Data Encryption(データ暗号化)
- Deployments(デプロイメント)
- Port Forwarding(ポート転送)
- Logs(ログ取得)
- Exec(コマンド実行)
Services(サービス)
Data Encryptionのテスト etcd内のSecretが暗号化されているか確認する。
kubectl create secret generic kubernetes-the-hard-way \ --from-literal="mykey=mydata" --- on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?] ♥ ❯ kubectl create secret generic kubernetes-the-hard-way \ --from-literal="mykey=mydata" secret/kubernetes-the-hard-way created on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?] ♥
kubectl create deployment nginx --image=nginx:latest kubectl get pods -l app=nginx --- on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?] ♥ ❯ kubectl create deployment nginx --image=nginx:latest deployment.apps/nginx created on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?] ♥ ❯ kubectl get pods -l app=nginx NAME READY STATUS RESTARTS AGE nginx-56fcf95486-nqght 1/1 Running 0 12s on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?] ♥
- Port Forwardingのテスト
- nginxへのポート転送
POD_NAME=$(kubectl get pods -l app=nginx -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward $POD_NAME 8080:80 &
curl --head http://127.0.0.1:8080
---
on ☸ admin on kubernetes-the-hard-way in default () haskell-sandbox/playground/algogogo on master via λ took 7d11h24m36s
♥ ❯ curl --head http://127.0.0.1:8080
HTTP/1.1 200 OK
Server: nginx/1.29.2
Date: Sat, 25 Oct 2025 23:37:30 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Tue, 07 Oct 2025 17:04:07 GMT
Connection: keep-alive
ETag: "68e54807-267"
Accept-Ranges: bytes
on ☸ admin on kubernetes-the-hard-way in default () haskell-sandbox/playground/algogogo on master via λ
♥
- ポート転送を停止
pkill -f "fort-forward"
- Logsのテスト
# nginxのログ kubectl logs $POD_NAME --- on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?] ✦ ♥ ❯ kubectl logs $POD_NAME /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/ /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh /docker-entrypoint.sh: Configuration complete; ready for start up 2025/10/25 23:33:15 [notice] 1#1: using the "epoll" event method 2025/10/25 23:33:15 [notice] 1#1: nginx/1.29.2 2025/10/25 23:33:15 [notice] 1#1: built by gcc 14.2.0 (Debian 14.2.0-19) 2025/10/25 23:33:15 [notice] 1#1: OS: Linux 5.15.0-157-generic 2025/10/25 23:33:15 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576 2025/10/25 23:33:15 [notice] 1#1: start worker processes 2025/10/25 23:33:15 [notice] 1#1: start worker process 29 2025/10/25 23:33:15 [notice] 1#1: start worker process 30 127.0.0.1 - - [25/Oct/2025:23:37:30 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/8.7.1" "-" on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?] ✦
- Execのテスト
- Pod内でコマンド実行
kubectl exec -ti $POD_NAME -- nginx -v --- on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?] ✦ ♥ ❯ kubectl exec -ti $POD_NAME -- nginx -v nginx version: nginx/1.29.2 on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?] ✦
- Servicesのテスト
- NodePort Serviceの作成
kubectl expose deployment nginx --port 80 --type NodePort kubectl get service nginx --- on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?] ✦ ♥ ❯ kubectl expose deployment nginx --port 80 --type NodePort service/nginx exposed on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?] ✦ ♥ ❯ kubectl get service nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx NodePort 10.32.0.189 <none> 80:31531/TCP 22s on ☸ admin on kubernetes-the-hard-way in default () new_lab/2025/kubernetes-hard-way on master [?] ✦
workerノードに接続できなかったのはPod Network Routesが不完全だったことが原因だった。
調査から
- tcpdump: SYNパケットは到達するが、SYN-ACKが返らない
- iptablesルール: 正しく設定されている
- Podへの直接アクセス失敗: curl http://10.200.1.3:80 がタイムアウト
- → これで「Pod間通信の問題」だと判明
解決方法
各workerノードに他のworkerのPod CIDRへのルートを追加
- 作業ログ
ubuntu@worker-0:~$ ip route default via 192.168.8.1 dev ens18 proto static 10.200.0.0/24 dev cnio0 proto kernel scope link src 10.200.0.1 192.168.8.0/24 dev ens18 proto kernel scope link src 192.168.8.20 ubuntu@worker-0:~$ sudo ip route add 10.200.1.0/24 via 192.168.8.21 ubuntu@worker-0:~$ sudo ip route add 10.200.2.0/24 via 192.168.8.22 ubuntu@worker-0:~$ ip route default via 192.168.8.1 dev ens18 proto static 10.200.0.0/24 dev cnio0 proto kernel scope link src 10.200.0.1 10.200.1.0/24 via 192.168.8.21 dev ens18 10.200.2.0/24 via 192.168.8.22 dev ens18 192.168.8.0/24 dev ens18 proto kernel scope link src 192.168.8.20 ubuntu@worker-0:~$ sudo vim /etc/netplan/01-netcfg.yaml ubuntu@worker-0:~$ sudo netplan apply ** (generate:39850): WARNING **: 00:56:01.769: Permissions for /etc/netplan/01-netcfg.yaml are too open. Netplan configuration should NOT be accessible by others. WARNING:root:Cannot call Open vSwitch: ovsdb-server.service is not running. ** (process:39848): WARNING **: 00:56:01.976: Permissions for /etc/netplan/01-netcfg.yaml are too open. Netplan configuration should NOT be accessible by others. ** (process:39848): WARNING **: 00:56:02.106: Permissions for /etc/netplan/01-netcfg.yaml are too open. Netplan configuration should NOT be accessible by others. ** (process:39848): WARNING **: 00:56:02.106: Permissions for /etc/netplan/01-netcfg.yaml are too open. Netplan configuration should NOT be accessible by others. ubuntu@worker-0:~$ curl -I http://10.200.1.3:80 HTTP/1.1 200 OK Server: nginx/1.29.2 Date: Sun, 26 Oct 2025 00:56:11 GMT Content-Type: text/html Content-Length: 615 Last-Modified: Tue, 07 Oct 2025 17:04:07 GMT Connection: keep-alive ETag: "68e54807-267" Accept-Ranges: bytes ubuntu@worker-0:~$ curl -I http://192.168.8.20:31531 HTTP/1.1 200 OK Server: nginx/1.29.2 Date: Sun, 26 Oct 2025 00:56:15 GMT Content-Type: text/html Content-Length: 615 Last-Modified: Tue, 07 Oct 2025 17:04:07 GMT Connection: keep-alive ETag: "68e54807-267" Accept-Ranges: bytes ubuntu@worker-0:~$
- 外部からのアクセステスト(オプション) gateway-01で実行
NODE_PORT=31531 sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.8.20:$NODE_PORT sudo netfilter-persistent save --- ubuntu@gateway-01:~$ NODE_PORT=31531 ubuntu@gateway-01:~$ sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.8.20:$NODE_PORT [sudo] password for ubuntu: ubuntu@gateway-01:~$ sudo netfilter-persistent save run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables save run-parts: executing /usr/share/netfilter-persistent/plugins.d/25-ip6tables save u
これにて完了!🎊
達成したこと
あなたは以下をゼロから手動で構築した:
Infrastructure
Kubernetes Control Plane
- 高可用性etcdクラスター(3ノード)
- kube-apiserver(3ノード)
- kube-controller-manager(3ノード)
- kube-scheduler(3ノード)
Kubernetes Workers
- containerd(コンテナランタイム)
- kubelet(3ノード)
- kube-proxy(3ノード)
- CNIネットワーク
Security & Networking
Add-ons
学んだこと
このチュートリアルを通して、以下を少し理解できた:
- Kubernetesのアーキテクチャ
- Control PlaneとWorker Nodesの役割
各コンポーネントの連携
- 証明書の生成と配布
相互認証の仕組み
ネットワーク
- Pod CIDR、Service CIDR
- ルーティング、NAT
NodePort、ClusterIP
セキュリティ
- RBAC
- データ暗号化
ネットワーク分離
高可用性
- etcdクラスタリング
- リーダー選出
- ロードバランシング
今後の学び
今までなんとなく仕事で感じていたモヤモヤを言語化できた話
0. この記事について
ソフトウェアエンジニアが向き合う抽象的な課題では、「抽象的な目線」と「具体的な作業」を行き来することで課題の本質を明確にし、作業の方向性をブレさせないことが重要です。この記事では、この考え方や実践方法について私の経験や考えた事を記載しています。
1. はじめに
新しい会社で働くようになり、あることを強く実感しました。
タスクを完了してレビューを受ける際に、「あれ?AC(アクセプタンス・クライテリア)と一致していない?」や「そもそもこのタスクのACを満たしていなかった? このタスクはACを満たすための事前調査だったのか? 実は調査→資料作成→関係者への展開までが1セットなのでは……」といったように、チームが期待しているタスク内容と自分が実施しているタスク内容に大きな乖離があることに気づきました。
「インフラエンジニアという未経験の分野だから仕方がない」「ウォーターフォール型開発が中心だった自分が、初めてスクラム開発を経験しているから仕方がない」など、言い訳を挙げればキリがありませんが、自分だけがチームの歩調に合っていない現状に焦りを感じていました。
上司が想定している成果物と私が提出した成果物の間には、なぜこれほどの乖離があるのか悩んでいました。
2. 問題の本質を探る
2.1 過去の具体的なタスク例
これまで私が受けていた仕事の依頼は、次のように非常に具体的な内容が多かったです。
- 「キャンペーン用にこのようなページを作成してください。テーブルはこうして……画面デザインはこうしてください。」
- 「Pythonを使って、ここからパケットを取得するツールを作成してください。」
- 「こういったシステムを作成したいので、外部設計書を作成してください。」
2.2 現在の抽象的な課題
一方、現在の会社では、以下のような「課題解決を委ねられる」依頼が増えていると感じています。
- 「○○がEOLになるのでどうにか対応してほしい。」
- 「△△というサービスが終了するため、移行を進めたい。」
こうした依頼に対して、とりあえず今まで通り「まずはやってみる」というスタンスで進めてみたものの、気づけば「調査資料を作成すること」が目的になってしまい、本来の目的である「関係者への周知や行動の促進」が抜け落ちてしまいました。そのため、作成すべき資料の内容も、インフラ以外の関係者に配慮した抽象的な内容が求められていたことに後から気づく始末でした。
3. 自己研鑽の試み
こうした課題を克服したい一心で、「課題解決」と名のつく自己啓発書やビジネス書を片っ端から読みました。しかし、どれも似たような内容で腑に落ちず、悶々とした日々を過ごしていました。そんな中、ある日出会った本に衝撃を受けました。それが、具体と抽象という一冊です。
4. 「具体」と「抽象」の視点
4.1 上司と自分の視点の違い
この本を通じて、「抽象的な視点」と「具体的な視点」という二つの視点の存在を知りました。この概念を知ったことで、上司と私の間で成果物に対する認識がズレている理由を理解することができました。
上司は抽象的な視点でタスクを見ており、タスクそのものではなく、それが包含している課題にフォーカスしています。そのため、後続のタスクや背景を意識しながら、課題に対して適切な成果物を作成できます。
一方で、私は具体的な視点しか持たず、タスク一つひとつに集中していました。その結果、解決すべき課題の本筋から外れた成果物を作成してしまい、後続のタスクに活用できない状況が生まれていました。
4.2 抽象的課題を具体化するプロセス
抽象という視点を知ることで、これまでの働き方におけるタスクの本質を理解できた気がします。たとえば、以下のように考えれば腑に落ちます。
- 「キャンペーンをやるのでページを作成してほしい」
→「売上を上げるために施策を打ちたい」
→「顧客が登録すれば売上が上がるかもしれない」
→「登録者数を増やすためにキャンペーンを打とう」
→「そのためのページ作成」という具体的なタスク。
5. 課題解決に向けての実践
5.1 本質を明確にする重要性
抽象的な課題を具体的な課題に変えるためには、「本質を明確にすること」が重要です。その上で、以下のような施策も有効だと感じています。
5.2 その他の実践的な施策
- アウトラインの確認を行う。
- 部分ごとに進捗を確認する(定期的な状況共有)。
- ビッグバンリリースを避け、叩き台を作成する。
- 手段が目的化しないように、一歩引いた視点でタスクを見直す。
6. おわりに
私自身、まだまだ実践できていないことも多いですが、これらを意識して仕事に取り組んでいこうと思います。
ソフトウェアエンジニアの仕事は本当に難しいですね……。
AWSネットワーク入門 第2版の所感
AWSネットワーク入門 第2版を読んでAWSのネットワークについて学んだので、 各章で学んだことや所感を書こうと思います。
※ 本にはリソースを削除するお掃除について、一部のリソースは記載がないのでハンズオンが一通り終わったらお掃除をしましょう!
所感
AWSのネットワークの基礎を学ぶにはいい本だと思います。 1~6章を読んでハンズオンをやるとWordPressが動かせるまで構築が完了するので、他のアプリにも応用ができそうです。 インフラエンジニアやクラウドエンジニアは7,8章も併せて読んでおくてAWSおよびドメイン周りの理解が深まります。 入門と書いてある通り業務で使うような突っ込んだ知識は得にくいのかなと感じました。特に7章のALBやRoute53周りで加重ルーティングの説明は欲しかったですが入門書などのそこまで深い知識はいらないですね。 業務でインフラ周りを担当しているエンジニアはAWSのネットワークについてさらに突っ込んだ本を読むか公式のハンズオンを実施する方が知識が身につくのかなという所感でした。
1章
AWSとオンプレの比較やネットワークの基礎知識を学びました。 ネットワークの本に書いてあることがつらつらと書いてありました。 データセンターを例にAWSのネットワークを説明しててわかりやすかったです。 グローバル、リージョン、アベイラビリティゾーンサービスの区別を覚えました。(今までなんとなくで覚えてました。 今までAWSのアーキテクチャ図を軽くではありますが読んできたので、本に書いてある簡易なアーキテクチャは苦も無く理解できました。
2章
VPCについて学びました。 実際に手を動かしてVPCやサブネットを構築するハンズオンを実施したり、CIDRなどの座学をざっくりと学びました。 デフォルトVPCは削除しても再作成が可能だとわかりました。
3章
EC2やEBSについて学びました。 T,M,C,X,R,G,I,Dシリーズの用途を知れて勉強になりました。 ハンズオンでEC2を構築して、ENIの確認などをしました。
4章
パブリックIPアドレス割り当て→IGW設定→ルートテーブル設定→Elastic IPの割り当てまで行いました。 あまりElastic IPの割り当てまでは実施しないので勉強になりました。 AWSネットワーク上にはメタデータを配信するHTTPサーバーが存在するそうです。 https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html
5章
セキュリティグループとネットワークACLについて学びました。 セキュリティグループ:ENI単位で設定するパケットフィルタリング機能 ネットワークACL:サブネット単位で設定するパケットフィルタリング機能 Appacheサーバーを導入して、セキュリティグループのインバウンドに HTTPとHTTPSを追加して接続できることを確認しました。
6章
プライベートサブネットのDBサーバーをNATゲートウェイから通信させました。 DBサーバーにMariaDBをインストールしてWordPressを起動するチュートリアルがありましたが、既知の情報だったので飛ばしました。 Elastic IPやNATゲートウェイはお金がかかるので閉じ忘れないように注意しないといけないです。
7章
Route53とELBについて学びました。 Route53を使用してドメインを取得していましたが、その部分はスキップしています。 ELBはALBを使用してwebserverを2台に冗長化させて構築しました。
8章
S3などの非VPCサービスを接続する方法として、インターフェイスエンドポイントとゲートウェイエンドポイントを構築して通信しました。 後半はVPCピアリングや外部ネットワークとの接続方法を書いてありましたが、ハンズオンは実施しませんでした。
「Team Geek ―Googleのギークたちはいかにしてチームを作るのか」を読んだので感想
未経験でインフラチームのリーダーになるという無茶振りを受けた際に、本の背に書いてあったGoogleのギークたちはいかにしてチームを作るのかの文に惹かれて買って読んでから半年後にはなりますが感想を書いていこうと思います。
先に読んだ感想を先に書くとこんな組織で働いてみたい/こういう組織を作らなきゃと思いました!
特に私は現職がパワハラと長時間労働で退職してしまうので、この本に書いてある組織に所属していたらもう少し長く働けてたのになぁと思うのと、今後私が組織作りに携わることになったらこのような組織を作っていかないと心理的安全性は担保できないなと思いました。
1章ずつ参考になった箇所や感動した部分をメモ書き程度に書いてきます。最後に書く余力があれば感想でも一行くらい書ければなと思います。
1章
- エンジニアリングチームの成功
謙虚・尊敬・信頼の原則が必要- この原則は何度も出てき来るのでとても重要な考え方です。
- アイデアは隠さない
- 早い段階で、高速に、何度も失敗せよの精神が大切
- この精神のおかげで私の作るものは早めに作り切ることにしました。
- 早い段階で、高速に、何度も失敗せよの精神が大切
- チームで開発する意味
- 一人で仕事するのはリスクが高い
- フィードバックがもらえない
- 自分の価値をコードに結びつけない
- 切り離して考える
- コードレビューのコメントや指摘は丁寧に攻撃的にならないように心がけたいです。
- 切り離して考える
2章
- チーム全員でプロダクトの成功に強い責任感を持つ
- 客先常駐だとなかなかできない考え方だなと思いました。
- 見栄を張るような文化は攻撃的な人を惹きつける
- 私のいた会社がまさにこのような会社でした。
- 3~4時間はスケジュールをブロックして、仕事を片付ける
- これは是非次に行く会社や現場でやってみようと思います。
3章
- 伝統的なマネージャーはどうやって仕事を完了させるか考える、リーダーは何ができるか考える。(仕事の完了させ方はチームに考えてもらう)
- 私も前者の考えになりがちなので、もっとチームメンバーに相談するべきでした…
- サーバントリーダー
- チームに奉仕し続けること。
HRTの雰囲気を作る- 今までのSIerとは求められるリーダーの理想像が逆ですよね。
- チームに奉仕し続けること。
- アンチパターンについて
- 自分の言いなりになる人の採用、採用を妥協する
- 会社がまさに10人入って10人出ていく会社だったのでこれに当てはまると思います。
- パフォーマンスの低い人の無視、人間の問題を無視する
- PMがまさにこの問題を持っていて、プロダクトの成長にしか興味がない人でした。
- みんなの友達になる
- 私がよくやってしまうパターンです。中々人に意見を言えませんでした。
- 自分の言いなりになる人の採用、採用を妥協する
- エゴをなくす
- 個人のエゴではなく、チームのエゴを育てる
- 今後を私がチームリーダーになった時に課題にしたいです。
- 個人のエゴではなく、チームのエゴを育てる
- 失敗の責任は追及しない。
- 詰めることはダメ絶対ですよね
- 褒めた言葉のサンドイッチではなく伝えたいことがははっきり言う
- 本当に伝えたいことが伝わらない。
- 建設的な批判をするときは親身になって相手の立場に立って考える
- 1vs1ミーティングの後に「何か必要なものはある?」と聞いてみたらいい
- リーダーになった際はやってみようと思います。
4章
- 排除するのはあくまでふるまいであって、個人ではない
- 個人の人格攻撃をしてはいけない
- なぜなぜ分析などは人格否定になりがちなので気をつけたいです。
- 個人の人格攻撃をしてはいけない
- 短期的なメリットで文化を妥協しない
- 長期的に考えた組織づくり、文化づくりをする。
- 妥協して誰でもいいから採用するというのはよくないですね。
- 長期的に考えた組織づくり、文化づくりをする。
5章
- 大人らしく振る舞う、質問する、マネージャーはエスパーではない
- 自分が期待することを伝える。
- 伝えないと相手はわからないですよね。
- 納得できないことをマネージャーが決めたら、根拠について質問したり討論したりする。
- これは私がやるべきでした。
- リーダーに聞かれる前に、こちらから何をしているか報告する。
- 新人の頃に言われたことだが、最近中々できてないです。
- 自分が期待することを伝える。
- 悪い習慣をやめることはできない。良い習慣と置き換えなければいけない。
- 私にとっては断酒することがこれにあたると思います。
- できないことは約束しない。
- 適当に見積もって締め切りを延ばすのではなく、Noと言う。
- 約束は小さくして、届けるものは大きくする。
- Noと言えない性格なので、これは難しいですね。
- 会社を辞めるときは、つながりを絶やさないようにしよう。
- うーん。現職では難しいかも…
6章
- Lispは今もなお最高のプログラミング言語だ
- 自分も少し触ってみようかな
- その人が言っていることを文字通りに解釈するのではなく、何を意図しているかを理解する
- とても大事だと思います。特に今の日本のSNSは文字通りに受け取り口論になる人が多いように感じます。
- そのソフトウェアは君のためではない。チームのためではない。会社のためではない。ユーザーの生活を豊かにするためである。
- 自分や会社のためと思って作りがちですが、ユーザーのために作ることを意識していきたいです。プロダクト開発の現場では必須の考え方だと思います。
感想
HRT(謙虚・尊敬・信頼)を用いて、自分の内面からチームについて、リーダーについて、アンチパターンについて考えさせられる本でした。
どうしてもチームでリーダーとして働いていると、生産性を出せていない人に対してその振る舞いを指摘することができず、その人の振る舞いを無視してチームを考えることが多かったのですが、HRTを用いてその人の気持ちに寄り添いながら、その人がどういう状況でそのような振る舞いについて親身なって指摘することができるようになりたいと思いました。
またHRTの文化のあるチームに所属することやまたチームを変えていくには、自分自身がHRTを体現することが必要だと考えました。
本気で学ぶ Linux実践入門 サーバ運用のための業務レベル管理術をよんだので感想
本気で学ぶ Linux実践入門 サーバ運用のための業務レベル管理術を少し前に読んだので感想を書きいていきます。
(かなりうろ覚えです)
この本はUbuntu(Debian系)とCentOS(レッドバット系)の二つのOSの視点から各コマンドの動作を確認できるので、現場にあるほとんどのサーバーに対して知識をつけることができます。
自分は今回やらなかったのですが、DockerやVirtualBoxを使って仮想環境を構築して本に記載されているコマンドを実行してみると更に深く学べると思います。
個人的に良かったと思う点はsystemdとブートシーケンスについて書かれている点だと思います。
コマンドが網羅されているコマンド集にはsystemdも言及はないため勉強になりました。
実際にsystemctlコマンドを使用してhttpdなど各種デーモンを起動、実行していくチュートリアルもあります。
今後もLinux環境を構築するときに手元に置いてリファレンス的に読んでいくにはいい本だと思いました。
時間があるときにDockerで仮想環境を建てて色々なコマンドを試してみよう思います!