Kubernetes 環境構築 Proxy編
Kubernetes(以下、K8s)をイントラネット内で構築する手順です。
K8s環境構築の流れを理解しつつ、作業はなるべくコピペで可能なように記載しています。
1. モチベーション
- K8sを会社内の開発イントラネット内環境で構築したい。
(プロキシサーバ経由で開発イントラネット内環境からインターネットにアクセスできる場合) - K8sを使ってみたいが、構築のハードルが高い。
2. 手順
本手順で以下のK8sクラスタ構成を構築します。
- 準備するもの
- OS : Centos7.4(minimal)
- PC 3台 ※仮想でも可
- CPU 2Core 以上
- Memroy 2GB 以上
- 出来上がるもの
- K8s クラスタ構成 ※Masterはシングル
- Master
- Worker
- Worker
- K8s クラスタ構成 ※Masterはシングル
2.1. Docker環境の構築(全ノード対象)
K8sは複数ノードにまたがりコンテナの駆動を管理するツールで、実際のコンテナの実行はDockerを経由しています。
また、K8sの機能もコンテナとして動作しているため、クラスタの全ノードでDockerが動作することが必要です。
すでにDockerが使えている場合は先に進んでもらって結構です。
ただし、※公式推奨と ※後述の作業に必要 の作業は確認しておいてください。
2.1.1. CentOS7のインストール(CLI)と基本設定
- CentOSをインストールします。
- 開発イントラネット内通信が可能となる設定をし、ローカルネットワークに接続可能な状態にしておきます。
IP,サブネットマスクの固定/MACアドレス登録など - swapを無効化します。 ※公式推奨
- SELINUX無効化してOS再起動します。
- yumのプロキシ設定
vi /etc/yum.conf で以下のように編集→保存
#swapを無効化
swapoff -a
sed -i -e "/swap/d" /etc/fstab
cat /etc/fstab
#SELINUX無効化してOS再起動
sed -i -e "s/^SELINUX=enforcing$/SELINUX=disabled/g" /etc/selinux/config
reboot
#yumのプロキシ設定
cat <<EOF >> /etc/yum.conf
proxy=http://{プロキシIP}:{プロキシポート}
EOF
2.1.2. Dockerのインストールと設定
- Dockerインストールします。 最後にバージョンが表示されれば成功です。
- Dockerのネットワーク設定1 ※後述の作業に必要 とhello-worldコンテナの実行をします。
- うまく行かない場合は、プロキシ設定を確認します。
#Dockerインストール
yum install -y yum-utils device-mapper-persistent-data lvm2 #Docker ceに必要なパッケージ
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo #Docker ceのリポジトリ追加
yum install -y --setopt=obsoletes=0 docker-ce-18.06.1.ce #Docker ceインストール
docker version #Dockerバージョン確認
↓Dockerバージョン確認結果
Client:
Version: 18.06.1-ce
API version: 1.38
Go version: go1.10.3
Git commit: e68fc7a
Built: Tue Aug 21 17:23:03 2018
OS/Arch: linux/amd64
Experimental: false
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
[root@K8sWorker1 ~]# docker version #Dockerバージョン確認
Client:
Version: 18.06.1-ce
API version: 1.38
Go version: go1.10.3
Git commit: e68fc7a
Built: Tue Aug 21 17:23:03 2018
OS/Arch: linux/amd64
Experimental: false
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
#Dockerのネットワーク設定
systemctl disable firewalld #Firewall無効化
systemctl stop firewalld #Firewall停止
mkdir -p /etc/systemd/system/docker.service.d # dockerのプロキシ設定
cat <<EOF > /etc/systemd/system/docker.service.d/http-proxy.conf #Proxy設定
[Service]
Environment="HTTP_PROXY=http://{プロキシIP}:{プロキシポート}" "HTTPS_PROXY=http://{プロキシIP}:{プロキシポート}" "NO_PROXY=localhost,127.0.0.1,10.96.0.0/12,10.244.0.0/16,{master nodeのIPアドレス},{worker node1のIPアドレス},{worker node2のIPアドレス}"
EOF
systemctl daemon-reload #プロキシ反映
systemctl enable docker && systemctl start docker #Docker再起動
docker run --rm hello-world #hello-worldコンテナ起動
↓ hello-worldコンテナ起動結果
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
(amd64)
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
https://hub.docker.com/
For more examples and ideas, visit:
https://docs.docker.com/get-started/
# プロキシ設定を確認
docker info | grep Proxy
2.2. kubeadmインストール~kubelet有効化 (全ノード対象)
2.2.1. kubeadmインストール
#kubeadmのためのプロキシを設定してOS再起動
cat <<EOF >> ~/.bash_profile
PROXY_PORT={プロキシポート}
PROXY_HOST={プロキシIP}
http_proxy=http://\$PROXY_HOST:\$PROXY_PORT
HTTP_PROXY=\$http_proxy
https_proxy=\$http_proxy
HTTPS_PROXY=\$http_proxy
no_proxy="localhost,127.0.0.1,10.96.0.0/12,10.244.0.0/16,{master nodeのIPアドレス},{worker node1のIPアドレス},{worker node2のIPアドレス}"
EOF
reboot
#k8sのためのyumリポジトリを追加
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
sslverify=0
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
#kubeadmと関連パッケージのインストール
yum install -y kubelet-1.16.0-0.x86_64 kubeadm-1.16.0-0.x86_64 kubectl-1.16.0-0.x86_64 --disableexcludes=kubernetes
2.2.2. kubelet有効化
- リソース管理ドライバをcgroupfsに統一します。
※Docker daemonの設定(デフォルトではsystemd)をkubelet側(cgroupfs)に合わせる。 - kubelet有効化と確認をします。※起動してなくてOK
- ブリッジの設定をします。
#リソース管理ドライバをcgroupfsに統一
cat << EOF > /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=cgroupfs"]
}
EOF
systemctl restart docker
docker info | grep -i cgroup
# kubelet有効化と確認
systemctl enable kubelet && systemctl start kubelet
systemctl status kubelet
↓ kubelet確認
● kubelet.service - kubelet: The Kubernetes Node Agent
Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)
Drop-In: /usr/lib/systemd/system/kubelet.service.d
mq10-kubeadm.conf
Active: activating (auto-restart) (Result: exit-code) since Tue 2020-06-02 17:00:13 JST; 932ms ago
Docs: https://kubernetes.io/docs/
Process: 16490 ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS (code=exited, status=255)
Main PID: 16490 (code=exited, status=255)
Jun 02 17:00:13 K8sWorker2.localdomain systemd[1]: Unit kubelet.service enter...
Jun 02 17:00:13 K8sWorker2.localdomain systemd[1]: kubelet.service failed.
Hint: Some lines were ellipsized, use -l to show in full.
#ブリッジの設定
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system
2.3. K8sクラスタ構築
2.3.1. Masterの構築 (Masterノード対象)
この作業はMasterノードでのみ行います。
- /tmpに以下のファイルを配置しておきます。
https://github.com/coreos/flannel/blob/master/Documentation/kube-flannel.yml
kube-flannel-ds-amd64がPullできない場合があります。
kube-flannel.ymlを編集し、今回はイメージのロード先を easzlabに変更しました。 ※2020/06/02 時点
- kubeadmを実行します。
tokenが出力されるので控えておきます。 - 設定の編集をします。
最後にcreatedが10個表示されればOK - Podを確認します。
Podが8個あり、すべてRunningになっていればOK
# イメージのロード先変更 ※他箇所あり
initContainers:
- name: install-cni
image: easzlab/flannel:v0.12.0-amd64
command:
#kubeadmを実行
kubeadm init --kubernetes-version 1.16.0 --apiserver-advertise-address={master nodeのIPアドレス} --pod-network-cidr=10.244.0.0/16 --token-ttl 0 --image-repository gotok8s
↓kubeadmを実行結果
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/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join {master nodeのip}:6443 --token oe4by1.8wxrpf52w2y6xulw \
--discovery-token-ca-cert-hash sha256:a184db6aaaa3529ea9cb4f46038945ceae4878e16f21213aac1a605583071d19
# 設定の編集
mkdir -p $HOME/.kube #これをやらないと動作しない場合あり。
sudo cp -f /etc/kubernetes/admin.conf $HOME/.kube/config #これをやらないと動作しない場合あり。
sudo chown $(id -u):$(id -g) $HOME/.kube/config #これをやらないと動作しない場合あり。
kubectl apply -f /tmp/kube-flannel.yml #kube-flannel設定反映
#Podを確認
kubectl get pods --all-namespaces
↓Pod確認結果
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-8655596978-ff4rv 1/1 Running 0 69s
kube-system coredns-8655596978-tprdp 1/1 Running 0 69s
kube-system etcd-k8smaster1.localdomain 1/1 Running 0 27s
kube-system kube-apiserver-k8smaster1.localdomain 1/1 Running 0 19s
kube-system kube-controller-manager-k8smaster1.localdomain 1/1 Running 0 12s
kube-system kube-flannel-ds-amd64-7vjkq 1/1 Running 0 37s
kube-system kube-proxy-4562b 1/1 Running 0 69s
kube-system kube-scheduler-k8smaster1.localdomain 1/1 Running 0 9s
2.3.2. Workerの構築 (Workerノード対象)
この作業はWorkderノードでのみ行います。
- Masterから設定のコピーをします。
- クラスターに参加します。
#Masterから設定のコピー
mkdir -p /etc/cni/net.d/
scp {master nodeのIPアドレス}:/etc/cni/net.d/10-flannel.conflist /etc/cni/net.d/10-flannel.conflist
#クラスターに参加
kubeadm join {master nodeのIPアドレス}:6443 --token {上述の作業で控えた値} \
--discovery-token-ca-cert-hash sha256:{上述の作業で控えた値}
2.3.3. ノードの確認
- それぞれのノードがクラスタに参加していることを確認します。
#ノードの確認
kubectl get nodes
↓ ノードの確認結果
NAME STATUS ROLES AGE VERSION
k8smaster1.localdomain Ready master 17h v1.16.0
k8sworker1.localdomain Ready <none> 2m26s v1.16.0
k8sworker2.localdomain Ready <none> 82s v1.16.0
3. 動作確認
3.1. ダッシュボードの表示
- 外部からアクセスできるようにrecommended.yamlを編集し、Masterノードの/tmpに配置しておきます。
https://github.com/kubernetes/dashboard - ダッシュボードのPodを作成します。
- admin-userを作成し、トークンを作ります。
- 以下URLにアクセスし、トークンを入力するとダッシュボードが開きます。
https://{master nodeのIP}:30843
---
# 外部からアクセスできるようにrecommended.yaml編集
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kubernetes-dashboard
spec:
type: NodePort #追加
ports:
- port: 443
targetPort: 8443
nodePort: 30843 #追加
selector:
k8s-app: kubernetes-dashboard
---
#ダッシュボードのPodを作成
kubectl apply -f /tmp/recommended.yaml
kubectl get pod --namespace=kubernetes-dashboard
# admin-userを作る
cat <<EOF > service-account.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kube-system
EOF
kubectl apply -f service-account.yaml #ユーザをデプロイ
kubectl -n kube-system get secret | grep admin #権限を表示
#トークン取得
kubectl -n kube-system describe secret admin-user-token-n72ds
3.2. コンテナ起動
コンテナを起動してみます。
3.2.1. Podのデプロイ
まずは、K8sではマニフェストファイル(YAML)を作成し、それをkubectl applyすることでコンテナをPodという単位で起動(デプロイ)します。
ここで気がつくのが、構築の時点でkubectl applyを使っていたということです。
つまり、K8sクラスターはポッドとサービスにより提供されているということです。
この段階では、クラスタノードからはコンテナにアクセスできるが外部からはアクセスできません。
3.2.2. サービスのデプロイ
外部からアクセスを可能にするために、サービスを追加しノードのポートとPodのポートを接続します。
3.2.1. Podのデプロイ
- Podをデプロイします。
- PodのIPを確認します。
- 確認したIPに対してアクセスしてみます。
Welcome to nginx!のHTML
が表示されます。 - ブラウザで
http://{PodのIP}:80
にアクセスしてみます。不能となります。
# Podをデプロイ
cd /tmp
cat <<EOF > deployments.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
EOF
kubectl apply -f deployments.yml
#PodのIPを確認
kubectl get pod -o wide
3.2.2. サービスのデプロイ
- サービスをデプロイします。
-
http://10.10.33.72:30036/
にアクセスします。Welcome to nginx!
のページが表示されます。
# サービスをデプロイ
cat <<EOF > service.yml
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
type: NodePort
ports:
- name: http
port: 80
targetPort: 80
nodePort: 30036
protocol: TCP
selector: # 1Pod複数コンテナの場合は、ココでパケットを振り分ける。
app: nginx
EOF
kubectl apply -f service.yml
4. まとめ
上述の手順で以下が達成できました。
- イントラネット環境内でK8sクラスターの構築
- 任意コンテナデプロイ
4.1. おさらい
- K8sはコンテナエンジンの上位レイヤのサービスであり、コンテナエンジンが駆動していることは前提条件(今回はDocker)
- K8sを駆動させるのに必要なものは以下
- 任意のコンテナはPodとサービスを使ってデプロイする。
4.2. 次のステップ
- ヘルスチェック・冗長性設定
- Master 兼 Worker設定
- イントラネット内コンテナレジストリ・レポジトリとの連携