はじめに
この記事で目指す構成は、ほぼタイトルの通りですが、
「kubeadmで作ったHA構成のk8sクラスタにIstioを入れて、HAProxyでプロキシする」
です。
kubeadm
公式で、将来的にもっと簡単にHA構成出来るようにすると言っているので、すぐに陳腐化するかもしれませんが…
想定するサーバー構成
- プロキシ
- マスターノード × n
- ワーカーノード × n
の構成を目指します。
僕は、ノードは2つずつの環境で作成しました。
使い方
タイトル通り、基本的には順番にコピペしていくだけです。
項目の頭にどのサーバー用のコマンド化が書いてあり、関連付けは以下の通りです。
頭文字 | サーバー |
---|---|
P | プロキシ |
M | マスターノード |
W | ワーカーノード |
記事中にスクリプトがいくつか出てきますが、変更可能個所がある場合は大体冒頭で変数を定義しています。
要件に合わせて、適宜変更してください。
記事中にいくつかコピペできないところが出てきますので、ご注意ください。
コピペコマンド
それでは、粛々とコピペしていきましょう。
[P/M/W] サーバー初期セットアップ
各種アップデートとタイムゾーン設定
sudo apt update && sudo apt upgrade -y
sudo timedatectl set-timezone Asia/Tokyo
[P] HAProxy のセットアップ
インストール
sudo apt install haproxy -y
cfgファイル作成
変数 | 値 |
---|---|
HOSTS | マスターノードのアドレス(スペース区切り、配列) |
HOSTS="192.168.1.110 192.168.1.111"
sudo mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg~
writeHost() {
sudo sh -c "cat << EOF >> /etc/haproxy/haproxy.cfg
# ==================
# $1
# ==================
frontend $1
bind *:$2
mode $3
default_backend $1
backend $1
balance roundrobin
mode $3
option tcp-check
EOF"
COUNT=1
for host in ${HOSTS}; do
sudo sh -c "cat << EOF >> /etc/haproxy/haproxy.cfg
server $1-${COUNT} ${host}:$2 check
EOF"
((COUNT++))
done
}
sudo sh -c "cat << EOF > /etc/haproxy/haproxy.cfg
# ==================
# global
# ==================
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
defaults
log global
mode http
option httplog clf
option dontlognull
EOF"
writeHost k8s-api 6443 tcp
writeHost k8s-http 80 http
# writeHost k8s-https 443
sudo service haproxy restart
writeHost k8s-http 80 http
の個所を適宜増やしていけば、他のポートにも対応可能です。
※HAProxyの前にさらにnginxがある場合
nginxの設定ファイルでproxy_http_version 1.1;
を設定しないと、エラー426が起こります。
istioがhttp1.0に対応していない事が原因なようです。
[M/W] Docker のセットアップ
インストール
sudo apt-get update
sudo apt-get install -y \
apt-transport-https \
ca-certificates \
curl \
gnupg-agent \
software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io
現在のユーザーで Docker を実行可能に
sudo groupadd docker
sudo usermod -aG docker $(id -u -n)
(Docker バージョン指定が必要な場合)
変数 | 値 |
---|---|
VERSION_STRING | インストールするDockerのバージョン |
sudo apt-cache showpkg docker-ce
VERSION_STRING=5:18.09.1~3-0~ubuntu-xenial
sudo apt-get install -y docker-ce=$VERSION_STRING docker-ce-cli=$VERSION_STRING containerd.io
[M/W] kubeadm のインストール
sudo apt-get update && sudo apt-get install -y apt-transport-https curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
sudo apt-add-repository "deb http://apt.kubernetes.io/ kubernetes-xenial main"
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
(kubeadm バージョン指定が必要な場合)
変数 | 値 |
---|---|
VERSION_STRING | インストールするDockerのバージョン |
sudo apt-cache showpkg kubeadm
VERSION_STRING=1.18.9-00
sudo apt install -y kubeadm=$VERSION_STRING kubelet=$VERSION_STRING kubectl=$VERSION_STRING
[M/W] swapを永続的にオフ
sudo swapoff -a
sudo sed -i 's:/swap.img:#/spap.img:g' /etc/fstab
[M] 最初のマスターノードセットアップ
kubeadm init
変数 | 値 |
---|---|
LOAD_BALANCER_DNS | HAProxyのアドレス |
LOAD_BALANCER_PORT | HAProxyが待ち受けているポート |
POD_SUBNET | calicoで使用するサブネット |
LOAD_BALANCER_DNS=192.168.1.120
LOAD_BALANCER_PORT=6443
POD_SUBNET=192.168.128.0/17
cat <<EOF > config.yaml
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: stable
apiServer:
certSANs:
- "${LOAD_BALANCER_DNS}"
controlPlaneEndpoint: "${LOAD_BALANCER_DNS}:${LOAD_BALANCER_PORT}"
networking:
podSubnet: "${POD_SUBNET}"
EOF
kubeadm config migrate --old-config config.yaml --new-config kubeadm-config.yaml
rm ~config.yaml
sudo kubeadm init --config=kubeadm-config.yaml
出力結果のコピーを忘れずに! ↓表示例(コピペコマンドではありません)
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
kubeadm join 192.168.1.120:6443 --token 77pipk.mh0vazty24yrhedt \
--discovery-token-ca-cert-hash sha256:99d7dd0f6774d12cb95bca85bf03a666f11d45a1d4a729808974073b405ea126 \
--control-plane
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.1.120:6443 --token 77pipk.mh0vazty24yrhedt \
--discovery-token-ca-cert-hash sha256:99d7dd0f6774d12cb95bca85bf03a666f11d45a1d4a729808974073b405ea126
設定のコピー
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
calicoを入れる
変数 | 値 |
---|---|
CIDR | calicoで使用するサブネット(先のPOD_SUBNETと同様) |
CIDR=192.168.128.0/17
curl -L -O https://docs.projectcalico.org/v3.8/manifests/calico.yaml
sed -i "s:192.168.0.0/16:${CIDR}:g" ./calico.yaml
kubectl apply -f ./calico.yaml
他のマスターに証明書を送信
sshが証明書認証になっていないと、 scp
コマンドの度にパスワードを聞かれます。
USER=$(id -u -n)
CONTROL_PLANE_IPS="192.168.1.110 192.168.1.111"
for host in ${CONTROL_PLANE_IPS}; do
sudo scp /etc/kubernetes/pki/ca.crt "${USER}"@$host:
sudo scp /etc/kubernetes/pki/ca.key "${USER}"@$host:
sudo scp /etc/kubernetes/pki/sa.key "${USER}"@$host:
sudo scp /etc/kubernetes/pki/sa.pub "${USER}"@$host:
sudo scp /etc/kubernetes/pki/front-proxy-ca.crt "${USER}"@$host:
sudo scp /etc/kubernetes/pki/front-proxy-ca.key "${USER}"@$host:
sudo scp /etc/kubernetes/pki/etcd/ca.crt "${USER}"@$host:etcd-ca.crt
sudo scp /etc/kubernetes/pki/etcd/ca.key "${USER}"@$host:etcd-ca.key
sudo scp /etc/kubernetes/admin.conf "${USER}"@$host:
done
[M] その他のマスターノードセットアップ
認証情報を適切な場所に配置
USER=$(id -u -n)
sudo mkdir -p /etc/kubernetes/pki/etcd
sudo mv /home/${USER}/ca.crt /etc/kubernetes/pki/
sudo mv /home/${USER}/ca.key /etc/kubernetes/pki/
sudo mv /home/${USER}/sa.pub /etc/kubernetes/pki/
sudo mv /home/${USER}/sa.key /etc/kubernetes/pki/
sudo mv /home/${USER}/front-proxy-ca.crt /etc/kubernetes/pki/
sudo mv /home/${USER}/front-proxy-ca.key /etc/kubernetes/pki/
sudo mv /home/${USER}/etcd-ca.crt /etc/kubernetes/pki/etcd/ca.crt
sudo mv /home/${USER}/etcd-ca.key /etc/kubernetes/pki/etcd/ca.key
sudo mv /home/${USER}/admin.conf /etc/kubernetes/admin.conf
kubeadm join
マスター1のkubeadm init
で得たコマンドのうち、--control-plane
がついている方をsudo
付きで実行します。
↓例(コピペコマンドではありません)
kubeadm join 192.168.1.120:6443 --token 77pipk.mh0vazty24yrhedt \
--discovery-token-ca-cert-hash sha256:99d7dd0f6774d12cb95bca85bf03a666f11d45a1d4a729808974073b405ea126 \
--control-plane
設定のコピー
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
[W] ワーカーノードセットアップ
マスター1のkubeadm init
で得たコマンドのうち、--control-plane
がついていない方をsudo
付きで実行します。
↓例(コピペコマンドではありません)
sudo kubeadm join 192.168.1.120:6443 --token 77pipk.mh0vazty24yrhedt \
--discovery-token-ca-cert-hash sha256:99d7dd0f6774d12cb95bca85bf03a666f11d45a1d4a729808974073b405ea126
トークンとシークレットが無効になった場合
こちらの記事を参照してください。
[M] istioのインストール
デフォルト状態でインストール
curl -L https://git.io/getLatestIstio | sh -
for f in ./istio*; do
cd $f
break
done
sudo mv bin/istioctl /usr/local/bin/
istioctl manifest apply -y
削除する場合
istioctl manifest generate --set profile=demo | kubectl delete -f -
デフォルト + ダッシュボードをインストール
curl -L https://git.io/getLatestIstio | sh -
for f in ./istio*; do
cd $f
break
done
sudo mv bin/istioctl /usr/local/bin/
istioctl manifest apply -y\
--set addonComponents.grafana.enabled=true\
--set addonComponents.kiali.enabled=true\
--set addonComponents.prometheus.enabled=true
削除する場合
istioctl manifest generate \
--set addonComponents.grafana.enabled=true\
--set addonComponents.kiali.enabled=true\
--set addonComponents.prometheus.enabled=true
| kubectl delete -f -
NodePortに変更
istio 1.5.1での設定です。
istio-ingressgateway
の type
を NodePort
に変更して、extenralIPs
に マスターノードのIPを列挙しています。
変数 | 値 |
---|---|
IPS | マスターノードのIP(スペース区切り、配列) |
IPS="192.168.1.110 192.168.1.111"
cat <<EOF > network.yaml
apiVersion: v1
kind: Service
metadata:
annotations: null
labels:
app: istio-ingressgateway
istio: ingressgateway
release: istio
name: istio-ingressgateway
namespace: istio-system
spec:
ports:
- name: status-port
port: 15020
targetPort: 15020
- name: http2
port: 80
targetPort: 80
- name: https
port: 443
- name: kiali
port: 15029
targetPort: 15029
- name: prometheus
port: 15030
targetPort: 15030 - name: grafana port: 15031 targetPort: 15031
- name: tracing
port: 15032
targetPort: 15032
- name: tls
port: 15443
targetPort: 15443
- name: tcp
port: 31400
selector:
app: istio-ingressgateway
istio: ingressgateway
type: NodePort
externalIPs:
EOF
for ip in ${IPS}; do
sh -c "cat << EOF >> network.yaml
- ${ip}
EOF"
done
kubectl apply -f network.yaml
envoyの自動インジェクト設定
変数 | 値 |
---|---|
NAMESPACE | 自動インジェクション対象の名前空間 |
NAMESPACE=ns-v1
kubectl label namespace ${NAMESPACE} istio-injection=enabled
(option) [M/W] プライベートDockerレジストリに対応
変数 | 値 |
---|---|
REGISTRY | プライベートDockerレジストリのアドレス |
注意: 名前空間が毎に保存されるので、対応したい名前空間が複数ある場合は namspace
の指定が必要です。
REGISTRY=registory.example.com
docker login $REGISTRY
DOCKERCONFIGJSON=$(cat ~/.docker/config.json | base64 -w 0)
cat <<EOF > private-registry-cred.yaml
apiVersion: v1
kind: Secret
metadata:
name: regcred
data:
.dockerconfigjson: ${DOCKERCONFIGJSON}
type: kubernetes.io/dockerconfigjson
EOF
kubectl apply -f private-registry-cred.yaml
この状態で、manifestにimagePullSecretsを追加すると、設定済みのプライベートDockerレジストリからpull可能になります。
apiVersion: v1
kind: Pod
metadata:
name: private-reg
spec:
containers:
- name: private-reg-container
image: <your-private-image>
imagePullSecrets:
- name: regcred
参考
https://docs.docker.com/install/linux/docker-ce/ubuntu/
https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
http://grugrut.hatenablog.jp/entry/2019/06/23/143533
https://qiita.com/megasys1968/items/b84f79b9c3f77de3d4a3
https://bbrfkr.hatenablog.jp/entry/2018/03/15/094536
https://esakat.github.io/esakat-blog/posts/kubernetes-dashboard-v2.0.0/
https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
istio
https://qiita.com/Ladicle/items/e949b0f68ac18b7a95d8
https://istio.io/docs/setup/getting-started/#uninstall
https://istio.io/docs/setup/install/istioctl/#generate-a-manifest-before-installation