Page History
| Table of Contents | ||
|---|---|---|
|
개요
kubeadm을 사용하여 고가용성 Kubernetes 클러스터를 설정하는 두 가지 접근 방식을 설명한다방식이 존재한다.
내부 클러스터 : 추가적 마스터 인프라가 필요하며 인프라 필요, etcd 구성과 플레인 노드가 같은 위치에 존재 해야 존재해야 한다.
외부 etcd 클러스터 역시 많은 인프라가 필요하며, : 추가적 인프라가 필요, 수평적 노드구성과 etcd 멤버가 가 분리되어 있어야 한다.
클러스터는 Kubernetes 버전 1.11 이상을 실행해야한다실행해야 한다.
kubeadm을 사용하여 HA 클러스터를 설정하는 것은 여전히 실험적이다.
예를 들어, 클러스터를 업그레이드하는 데 문제가 발생할때 두 방법 중 하나를 시도하고 피드백을 제공하는 것이 좋다.
시작하기전
두 가지 방법에 대한 다음 인프라 환경 두 가지 방법 모두 다음과 같은 추가적인 인프라 구성이 필요하다.
HA구성을 위한 kubeadm의 Kubeadm의 최소 요구 사항의 3대 물리서버사항을 충족시키는 3대의 마스터.
kubeadm의 최소 요구 사항을 충족하는 3 대의 기계
클러스터의 모든 컴퓨터 간 전체 네트워크 연결 (공용 또는 개인 네트워크가 정상 임)
Kubeadm의 최소 요구사항을 충족시키는 3대의 노드.
클러스터간 전체 네트워크 연결.
클러스터간 모든 한 장치에서 시스템의 모든 노드로 SSH 액세스.
모든 컴퓨터에서 sudo 권한, 외부 etcd 클러스터에 대해서만 필요함.
클러스트간 SUDU 권한.
외부 Etcd 클러스터 구성은 별도 3대의 서버가 추가로 필요하다etcd 회원을위한 3 대의 추가 기계.
SSH 설정
메인 장치에서 시스템의 다른 모든 노드에 액세스 할 수있는 ssh-agent를 활성화활성화가 필요하다.
| Code Block | ||
|---|---|---|
| ||
# eval $(ssh-agent) |
SSH ID를 세션에 추가.
| Code Block | ||
|---|---|---|
| ||
# ssh-add ~/.ssh/path_to_private_key |
노드 간 SSH를 사용하여 연결이 올바르게 작동하는지 체크
어떤 노드로 SSH 할 때 -A 플래그를 추가해야함
한다.
| Code Block | ||
|---|---|---|
| ||
# ssh -A 10.0.0.7 |
모든 노드에서 sudo를 사용할 때 SSH 전달이 작동하도록 환경을 보존 되어야 한다.
| Code Block | ||
|---|---|---|
| ||
# sudo -E -s |
SSH 간편 설정
| Code Block | ||
|---|---|---|
| ||
Master Node 1
$ rm -rf /root/.ssh/*
$ ssh <master ip 1> pwd
$ ssh <master ip 2> rm -rf /root/.ssh/*
$ ssh <master ip 3> rm -rf /root/.ssh/*
$ ssh <master ip 2> mkdir -p /root/.ssh/
$ ssh <master ip 3> mkdir -p /root/.ssh/
$ scp /root/.ssh/known_hosts root@<master ip 2>:/root/.ssh/
$ scp /root/.ssh/known_hosts root@<master ip 3>:/root/.ssh/
$ ssh-keygen -t rsa -P '' -f /root/.ssh/id_rsa
$ cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
$ scp /root/.ssh/authorized_keys root@<master ip 2>:/root/.ssh/
Master Node 2
$ ssh-keygen -t rsa -P '' -f /root/.ssh/id_rsa
$ cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
$ scp /root/.ssh/authorized_keys root@<master ip 3>:/root/.ssh/
Master Node 3
$ ssh-keygen -t rsa -P '' -f /root/.ssh/id_rsa
$ cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
$ scp /root/.ssh/authorized_keys root@<master ip 1>:/root/.ssh/
$ scp /root/.ssh/authorized_keys root@<master ip 2>:/root/.ssh/
# ssh -A <master ip 1>
# ssh -A <master ip 2>
# ssh -A <master ip 3> |
결과)
Last login: Mon Oct 1 12:35:56 2018
kube-apiserver Load Balancer 설정
로드 밸런서에는 많은 구성이 있으며, 다음은 그중 하나의 옵션사항 및 설치 내역이다.
DNS로 해석되는 이름을 가진 kube-apiserver로드 밸런서 생성. (클라우드 환경에서는 TCP forwarding로드 밸런서 뒤에 컨트롤 플레인 노드를 배치)
로드 밸런서는 트래픽을 대상 목록의 정상적인 모든 컨트롤 플레인 노드에 배포.
apiserver의 상태 검사는 kube-apiserver가 수신하는 포트의 TCP 검사 (기본값 : 6443).
로드 밸런서는 apiserver 포트의 모든 제어 플레인 노드와 통신 할 수 있어야 하며, 수신 포트에서 들어오는 트래픽을 허용해야한다.
모든 master node에 haproxy 와 keepalived 설치 (haproxy는 1.5 버전 이상부터 SSL 지원)
| Code Block | ||
|---|---|---|
| ||
# yum install haproxy
# haproxy -v
# yum install keepalived |
모든 master node에 chkconfig 설정 진행 (부팅시 자동 실행 on 설정)
아래 명령어는 구버전 명령어이며 실행은 되지만 최근 명령어 갱신이 필요하다.
| Code Block | ||
|---|---|---|
| ||
# chkconfig haproxy on && chkconfig keepalived on && chkconfig | egrep 'haproxy|keepalived' |
모든 master ndoe에 non-local Virtual IPs binding
| Code Block | ||
|---|---|---|
| ||
# echo "net.ipv4.ip_nonlocal_bind = 1" >> /etc/sysctl.conf && sysctl -p |
결과)
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.forwarding = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.ip_nonlocal_bind = 1
keepalived 설정 (All Master)
| Code Block | ||
|---|---|---|
| ||
# cd /etc/keepalived //원본 백업
# mv keepalived.conf keepalived.conf.org |
Master Node 1 설정
| Code Block | ||
|---|---|---|
| ||
# vi /etc/keepalived/keepalived.conf
global_defs {
notification_email {
test@test.com
test2 @test.com
}
notification_email_from lb1@test.com
smtp_server localhost
smtp_connect_timeout 30
}
# haproxy 활성화 체크
vrrp_script chk_haproxy {
script "killall -0 haproxy"
interval 2
weight 2
}
vrrp_instance VI_1 {
state MASTER
interface eth0 # 사용할 인터페이스 설정 (ifconfig 로확인 가능)
virtual_router_id 51 # Master Node 3대가 모두 같은 값이어야 한다. (최대 255까지설정가능)
priority 101 # 우선순위 설정 (최대 255까지 설정가능)
advert_int 1 # VRRP패킷 송신 간격 설정 (초단위로 지정)
authentication {
auth_type PASS # 평문 인증 설정
auth_pass 1111 # 인증을 위한 키 (All Master 동일값 설정)
}
virtual_ipaddress {
000.000.000.000 # VIP설정
}
track_script {
chk_haproxy
}
} |
Master Node 2 설정
※ Master Node 2 에서는 Master Node 1 과 동일하게 구성하되 priority와 라우터 아이디만 다르게 설정 한다.
| Code Block | ||
|---|---|---|
| ||
# vi /etc/keepalived/keepalived.conf
global_defs {
notification_email {
test@test.com
test2 @test.com
}
notification_email_from lb1@test.com
smtp_server localhost
smtp_connect_timeout 30
}
# haproxy 활성화 체크
vrrp_script chk_haproxy {
script "killall -0 haproxy"
interval 2
weight 2
}
vrrp_instance VI_2 {
state BACKUP
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
000.000.000.000
}
track_script {
chk_haproxy
}
} |
Master Node 3 설정
※ Master Node 3 에서는 Master Node 1,2 와 동일하게 구성하되 priority와 라우터 아이디만 다르게 설정 한다.
| Code Block | ||
|---|---|---|
| ||
# vi /etc/keepalived/keepalived.conf
global_defs {
notification_email {
test@test.com
test2 @test.com
}
notification_email_from lb1@test.com
smtp_server localhost
smtp_connect_timeout 30
}
# haproxy 활성화 체크
vrrp_script chk_haproxy {
script "killall -0 haproxy"
interval 2
weight 2
}
vrrp_instance VI_3 {
state BACKUP
interface eth0
virtual_router_id 51
priority 99
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
000.000.000.000
}
track_script {
chk_haproxy
}
} |
keepalived 실행 (All Master)
| Code Block | ||
|---|---|---|
| ||
# systemctl enable keepalived
# systemctl start keepalived |
결과)
● keepalived.service - LVS and VRRP High Availability Monitor
Loaded: loaded (/usr/lib/systemd/system/keepalived.service; enabled; vendor preset: disabled)
Active: active (running) since 월 2018-10-01 14:11:44 KST; 7s ago
Process: 26099 ExecStart=/usr/sbin/keepalived $KEEPALIVED_OPTIONS (code=exited, status=0/SUCCESS)
Main PID: 26100 (keepalived)
Tasks: 3
Memory: 1.6M
CGroup: /system.slice/keepalived.service
├─26100 /usr/sbin/keepalived -D
├─26101 /usr/sbin/keepalived -D
└─26102 /usr/sbin/keepalived -D
10월 01 14:11:46 sb-k8s-MASTER-STBY77 Keepalived_vrrp[26102]: Sending gratuitous ARP on eth0 for 222.231.50.9
10월 01 14:11:46 sb-k8s-MASTER-STBY77 Keepalived_vrrp[26102]: /usr/bin/killall -0 haproxy exited with status 1
10월 01 14:11:48 sb-k8s-MASTER-STBY77 Keepalived_vrrp[26102]: /usr/bin/killall -0 haproxy exited with status 1
10월 01 14:11:50 sb-k8s-MASTER-STBY77 Keepalived_vrrp[26102]: /usr/bin/killall -0 haproxy exited with status 1
10월 01 14:11:51 sb-k8s-MASTER-STBY77 Keepalived_vrrp[26102]: Sending gratuitous ARP on eth0 for 222.231.50.9
10월 01 14:11:51 sb-k8s-MASTER-STBY77 Keepalived_vrrp[26102]: VRRP_Instance(VI_1) Sending/queueing gratuitous ARPs on eth0 for 22....50.9
10월 01 14:11:51 sb-k8s-MASTER-STBY77 Keepalived_vrrp[26102]: Sending gratuitous ARP on eth0 for 222.231.50.9
10월 01 14:11:51 sb-k8s-MASTER-STBY77 Keepalived_vrrp[26102]: Sending gratuitous ARP on eth0 for 222.231.50.9
10월 01 14:11:51 sb-k8s-MASTER-STBY77 Keepalived_vrrp[26102]: Sending gratuitous ARP on eth0 for 222.231.50.9
10월 01 14:11:51 sb-k8s-MASTER-STBY77 Keepalived_vrrp[26102]: Sending gratuitous ARP on eth0 for 222.231.50.9
Hint: Some lines were ellipsized, use -l to show in full.
Master Node 가상 아이피 체크
| Code Block | ||
|---|---|---|
| ||
# ip addr show eth0 |
결과)
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:21:46:f3 brd ff:ff:ff:ff:ff:ff
inet <로컬 IP> brd 222.231.50.255 scope global eth0
valid_lft forever preferred_lft forever
inet <가상 IP> scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe21:46f3/64 scope link
valid_lft forever preferred_lft forever
// client node 서버에서 vip로 ping test후 arp cahce를 확인
// VIP 에대하여 node 1과 동일한 mac주소를 cahce 하고 있는것을 확인
| Code Block | ||
|---|---|---|
| ||
# arp -a |
결과)
? (192.168.000.000) at 00:50:56:fd:6b:11 [ether] on eth1
? (192.168.000.000) at 00:50:56:c0:00:08 [ether] on eth1
? (192.168.000.100) at 00:0c:29:c4:76:05 [ether] on eth1 <-------------VIP
? (192.168.000.101) at 00:0c:29:c4:76:05 [ether] on eth1 <--------------Node 1 IP
? (192.168.000.000) at 00:0c:29:bf:fb:82 [ether] on eth1
haproxy 설정 (All Master)
| Code Block | ||
|---|---|---|
| ||
# mv /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.org //원본 백업
# vi /etc/haproxy/haproxy.cfg
global
log 127.0.0.1 local2
maxconn 2000
uid 0
gid 0
daemon # background process
defaults
log global # global 설정 사용
mode tcp # SSL 통신을 위해서는 TCP모드로 (http모드는 SSL 안됨)
option tcplog
option dontlognull # 데이터가 전송되지 않은 연결 로깅 제외
retries 3 # 연결요청 재시도 횟수
maxconn 2000 #option redispatch
#timeout http-request 10s
#timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
frontend ssl_front
bind 000.000.000.000:16443 #VIP (kube-master 와 같은 머신을 사용하므로 port를 kube-api 서버와 다르게 설정)
default_backend ssl_backend
backend ssl_backend
balance roundrobin
option tcp-check # ssl-hello-chk option 사용하지 말것 - ssl3.0 protocol 이라 k8s api 서버 오류 유발 (TLS 1.2 이상만 지원)
server hostname1 000.000.000.000:6443 check
server hostname2 000.000.000.001:6443 check
server hostname3 000.000.000.002:6443 check |
haproxy 실행 (All Master)
| Code Block | ||
|---|---|---|
| ||
# systemctl enable haproxy
# systemctl start haproxy |
결과)
결과)
● haproxy.service - HAProxy Load Balancer
Loaded: loaded (/usr/lib/systemd/system/haproxy.service; enabled; vendor preset: disabled)
Active: active (running) since 월 2018-10-01 14:53:58 KST; 5s ago
Main PID: 6841 (haproxy-systemd)
Tasks: 3
Memory: 1.6M
CGroup: /system.slice/haproxy.service
├─6841 /usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid
├─6842 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
└─6843 /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
10월 01 14:53:58 sb-k8s-MASTER-STBY77 systemd[1]: Started HAProxy Load Balancer.
10월 01 14:53:58 sb-k8s-MASTER-STBY77 systemd[1]: Starting HAProxy Load Balancer...
10월 01 14:53:58 sb-k8s-MASTER-STBY77 haproxy-systemd-wrapper[6841]: haproxy-systemd-wrapper: executing /usr/sbin/haproxy -f /etc/... -Ds
Hint: Some lines were ellipsized, use -l to show in full.
kubeadm-config.yaml 설정
kubeadm init 실행 전 kubeadm-config.yaml 설정이 필요하다.
모든 Master Node 에 설정이 필수적으로 적용되어야 한다.
이 단계에서, HAProxy는 timeout 오류가 날 것이다. 왜냐하면 api-server는 지금 이 단계를 통해 살아나기 때문이다.
Master Node 1 설정
kubeadm-config.yaml 파일 생성 (root 경로 에서 작업)
Master Node Hostname 은 반드시 소문자를 사용해야 한다. IP를 사용하면 etcd 생성 실패로 kubeadm init 실행시 오류발생.
podSubnet: "192.168.0.0/16" : 지정할 가상 IP 대역 (없으면 생략 가능)
| Code Block | ||
|---|---|---|
| ||
# v1.11.0
apiVersion: kubeadm.k8s.io/v1alpha2
kind: MasterConfiguration
kubernetesVersion: v1.11.3
apiServerCertSANs:
- "{VIP}"
api:
controlPlaneEndpoint: "{VIP}:16443"
etcd:
local:
extraArgs:
listen-client-urls: "https://127.0.0.1:2379,https://{Master Node 1 IP}:2379"
advertise-client-urls: "https://{Master Node 1 IP}:2379"
listen-peer-urls: "https://{Master Node 1 IP}:2380"
initial-advertise-peer-urls: "https://{Master Node 1 IP}:2380"
initial-cluster: "{Master Node 1 Host Name}=https://{Master Node 1 IP}:2380"
serverCertSANs:
- {Master Node 1 Host Name}
- {Master Node 1 IP}
peerCertSANs:
- {Master Node 1 Host Name}
- {Master Node 1 IP}
networking:
podSubnet: "10.32.0.0/12"
================================================================================================
# v1.12.0
apiVersion: kubeadm.k8s.io/v1alpha3
kind: ClusterConfiguration
kubernetesVersion: v1.12.1
apiServerCertSANs:
- "{VIP}"
controlPlaneEndpoint: "{VIP}:16443"
etcd:
local:
extraArgs:
listen-client-urls: "https://127.0.0.1:2379,https://{Master Node 1 IP}:2379"
advertise-client-urls: "https://{Master Node 1 IP}:2379"
listen-peer-urls: "https://{Master Node 1 IP}:2380"
initial-advertise-peer-urls: "https://{Master Node 1 IP}:2380"
initial-cluster: "{Master Node 1 Host Name}=https://{Master Node 1 IP}:2380"
serverCertSANs:
- {Master Node 1 Host Name}
- {Master Node 1 IP}
peerCertSANs:
- {Master Node 1 Host Name}
- {Master Node 1 IP}
networking:
podSubnet: "10.32.0.0/12" |
Master Node 2 설정
| Code Block | ||
|---|---|---|
| ||
# v1.11.0
apiVersion: kubeadm.k8s.io/v1alpha2
kind: MasterConfiguration
kubernetesVersion: v1.11.3
apiServerCertSANs:
- "{VIP}"
api:
controlPlaneEndpoint: "{VIP}:16443"
etcd:
local:
extraArgs:
listen-client-urls: "https://127.0.0.1:2379,https://{Master Node 2 IP}:2379"
advertise-client-urls: "https://{Master Node 2 IP}:2379"
listen-peer-urls: "https://{Master Node 2 IP}:2380"
initial-advertise-peer-urls: "https://{Master Node 2 IP}:2380"
initial-cluster: "{Master Node 1 Host Name}=https://{Master Node 1 IP},{Master Node 2 Host Name}=https://{Master Node 2 IP}:2380"
initial-cluster-state: existing
serverCertSANs:
- {Master Node 2 Host Name}
- {Master Node 2 IP}
peerCertSANs:
- {Master Node 2 Host Name}
- {Master Node 2 IP}
networking:
podSubnet: "10.32.0.0/12"
================================================================================================
#v1.12.0
apiVersion: kubeadm.k8s.io/v1alpha3
kind: ClusterConfiguration
kubernetesVersion: v1.12.1
apiServerCertSANs:
- "{VIP}"
controlPlaneEndpoint: "{VIP}:16443"
etcd:
local:
extraArgs:
listen-client-urls: "https://127.0.0.1:2379,https://{Master Node 2 IP}:2379"
advertise-client-urls: "https://{Master Node 2 IP}:2379"
listen-peer-urls: "https://{Master Node 2 IP}:2380"
initial-advertise-peer-urls: "https://{Master Node 2 IP}:2380"
initial-cluster: "{Master Node 1 Host Name}=https://{Master Node 2 IP}:2380,{Master Node 2 Host Name}=https://{Master Node 2 IP}:2380"
initial-cluster-state: existing
serverCertSANs:
- {Master Node 2 Host Name}
- {Master Node 2 IP}
peerCertSANs:
- {Master Node 2 Host Name}
- {Master Node 2 IP}
networking:
podSubnet: "10.32.0.0/12" |
Master Node 3 설정
| Code Block | ||
|---|---|---|
| ||
# v1.11.0
apiVersion: kubeadm.k8s.io/v1alpha2
kind: MasterConfiguration
kubernetesVersion: v1.11.3
apiServerCertSANs:
- "{VIP}"
api:
controlPlaneEndpoint: "{VIP}:16443"
etcd:
local:
extraArgs:
listen-client-urls: "https://127.0.0.1:2379,https://{Master Node 3 IP}:2379"
advertise-client-urls: "https://{Master Node 3 IP}:2379"
listen-peer-urls: "https://{Master Node 3 IP}:2380"
initial-advertise-peer-urls: "https://{Master Node 3 IP}:2380"
initial-cluster: "{Master Node 1 Host Name}=https://{Master Node 1 IP}:2380,{Master Node 2 Host Name}=https://{Master Node 2 IP}:2380,{Master Node 3 Host Name}=https://{Master Node 3 IP}:2380"
initial-cluster-state: existing
serverCertSANs:
- {Master Node 3 Host Name}
- {Master Node 3 IP}
peerCertSANs:
- {Master Node 3 Host Name}
- {Master Node 3 IP}
networking:
podSubnet: "10.32.0.0/12"
================================================================================================
# v1.12.0
apiVersion: kubeadm.k8s.io/v1alpha3
kind: ClusterConfiguration
kubernetesVersion: v1.12.1
apiServerCertSANs:
- "{VIP}"
controlPlaneEndpoint: "{VIP}:16443"
etcd:
local:
extraArgs:
listen-client-urls: "https://127.0.0.1:2379,https://{Master Node 3 IP}:2379"
advertise-client-urls: "https://{Master Node 3 IP}:2379"
listen-peer-urls: "https://{Master Node 3 IP}:2380"
initial-advertise-peer-urls: "https://{Master Node 3 IP}:2380"
initial-cluster: "{Master Node 1 Host Name}=https://{Master Node 1 IP}:2380,{Master Node 2 Host Name}=https://{Master Node 2 IP}:2380,{Master Node 3 Host Name}=https://{Master Node 3 IP}:2380"
initial-cluster-state: existing
serverCertSANs:
- {Master Node 3 Host Name}
- {Master Node 3 IP}
peerCertSANs:
- {Master Node 3 Host Name}
- {Master Node 3 IP}
networking:
podSubnet: "10.32.0.0/12" |
Kubeadm Init
| Code Block | ||
|---|---|---|
| ||
# echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
# cat /proc/sys/net/ipv4/ip_forward //변경확인
# kubeadm init --config kubeadm-config.yaml |
결과)
I1001 16:33:49.306235 8091 version.go:89] could not fetch a Kubernetes version from the internet: unable to get URL "https://dl.k8s.io/release/stable.txt": Get https://dl.k8s.io/release/stable.txt: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
I1001 16:33:49.306486 8091 version.go:94] falling back to the local client version: v1.12.0
[init] using Kubernetes version: v1.12.0
[preflight] running pre-flight checks
[preflight/images] Pulling images required for setting up a Kubernetes cluster
[preflight/images] This might take a minute or two, depending on the speed of your internet connection
[preflight/images] You can also perform this action in beforehand using 'kubeadm config images pull'
[kubelet] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[preflight] Activating the kubelet service
[certificates] Generated etcd/ca certificate and key.
[certificates] Generated etcd/server certificate and key.
[certificates] etcd/server serving cert is signed for DNS names...
[certificates] Generated etcd/peer certificate and key.
[certificates] etcd/peer serving cert is signed for DNS names...
[certificates] Generated etcd/healthcheck-client certificate and key.
[certificates] Generated apiserver-etcd-client certificate and key.
[certificates] Generated ca certificate and key.
[certificates] Generated apiserver certificate and key.
[certificates] apiserver serving cert is signed for DNS names...
[certificates] Generated apiserver-kubelet-client certificate and key.
[certificates] Generated front-proxy-ca certificate and key.
[certificates] Generated front-proxy-client certificate and key.
[certificates] valid certificates and keys now exist in "/etc/kubernetes/pki"
[certificates] Generated sa key and public key.
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/admin.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/kubelet.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/controller-manager.conf"
[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/scheduler.conf"
[controlplane] wrote Static Pod manifest for component kube-apiserver to "/etc/kubernetes/manifests/kube-apiserver.yaml"
[controlplane] wrote Static Pod manifest for component kube-controller-manager to "/etc/kubernetes/manifests/kube-controller-manager.yaml"
[controlplane] wrote Static Pod manifest for component kube-scheduler to "/etc/kubernetes/manifests/kube-scheduler.yaml"
[etcd] Wrote Static Pod manifest for a local etcd instance to "/etc/kubernetes/manifests/etcd.yaml"
[init] waiting for the kubelet to boot up the control plane as Static Pods from directory "/etc/kubernetes/manifests"
[init] this might take a minute or longer if the control plane images have to be pulled
[apiclient] All control plane components are healthy after 21.504056 seconds
[uploadconfig] storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[kubelet] Creating a ConfigMap "kubelet-config-1.12" in namespace kube-system with the configuration for the kubelets in the cluster
[markmaster] Marking the node ... as master by adding the label "node-role.kubernetes.io/master=''"
[markmaster] Marking the node ... as master by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object...
[bootstraptoken] using token: ws83pk.dm7js0fvgkdkud3y
[bootstraptoken] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstraptoken] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstraptoken] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstraptoken] creating the "cluster-info" ConfigMap in the "kube-public" namespace
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy
Your Kubernetes master 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 machines by running the following on each node
as root:
kubeadm join ...
Master Node 1 Certification
Master Node 1에서 init 실행 후 생성된 각 인증 파일은 Master Node 2, 3에서도 동일하게 사용되어야 한다.
아래와 같이 Master Node 1에서 Master Node 2,3 으로 SSH 를 통한 인증파일을 복사한다.
| Code Block | ||
|---|---|---|
| ||
// 대상
/etc/kubernetes/pki/ca.crt
/etc/kubernetes/pki/ca.key
/etc/kubernetes/pki/sa.key
/etc/kubernetes/pki/sa.pub
/etc/kubernetes/pki/front-proxy-ca.crt
/etc/kubernetes/pki/front-proxy-ca.key
/etc/kubernetes/pki/etcd/ca.crt
/etc/kubernetes/pki/etcd/ca.key
/etc/kubernetes/admin.conf
// 실행
# USER=ubuntu # root 일경우는? (/root/ 경로로 복사됨)
# CONTROL_PLANE_IPS="10.0.0.7 10.0.0.8"
# for host in ${CONTROL_PLANE_IPS}; do
scp /etc/kubernetes/pki/ca.crt "${USER}"@$host:
scp /etc/kubernetes/pki/ca.key "${USER}"@$host:
scp /etc/kubernetes/pki/sa.key "${USER}"@$host:
scp /etc/kubernetes/pki/sa.pub "${USER}"@$host:
scp /etc/kubernetes/pki/front-proxy-ca.crt "${USER}"@$host:
scp /etc/kubernetes/pki/front-proxy-ca.key "${USER}"@$host:
scp /etc/kubernetes/pki/etcd/ca.crt "${USER}"@$host:etcd-ca.crt
scp /etc/kubernetes/pki/etcd/ca.key "${USER}"@$host:etcd-ca.key
scp /etc/kubernetes/admin.conf "${USER}"@$host:
done |
Master Node 2 Bootstrap
Master Node 1 에서 복사된 인증파일은 Master Node 2 에서 Bootstrap 구성시 인증으로 쓰인다.
※ 여기에서 copy 및 move 는 별도의 sh 스크립트를 만들어 사용하면 빠르다.
| Code Block | ||
|---|---|---|
| ||
// 이동
mkdir -p /etc/kubernetes/pki/etcd
mv /root/ca.crt /etc/kubernetes/pki/
mv /root/ca.key /etc/kubernetes/pki/
mv /root/sa.pub /etc/kubernetes/pki/
mv /root/sa.key /etc/kubernetes/pki/
mv /root/front-proxy-ca.crt /etc/kubernetes/pki/
mv /root/front-proxy-ca.key /etc/kubernetes/pki/
mv /root/etcd-ca.crt /etc/kubernetes/pki/etcd/ca.crt
mv /root/etcd-ca.key /etc/kubernetes/pki/etcd/ca.key
mv /root/admin.conf /etc/kubernetes/admin.conf
# kubeadm alpha phase certs all --config kubeadm-config.yaml
# kubeadm alpha phase kubelet config write-to-disk --config kubeadm-config.yaml
# kubeadm alpha phase kubelet write-env-file --config kubeadm-config.yaml
# kubeadm alpha phase kubeconfig kubelet --config kubeadm-config.yaml
# systemctl start kubelet |
Master Node 2 Cluster
| Code Block | ||
|---|---|---|
| ||
# export CP0_IP={Master Node 1 IP}
# export CP0_HOSTNAME={Master Node 1 Host Name}
# export CP1_IP={Master Node 2 IP}
# export CP1_HOSTNAME={Master Node 2 Host Name}
# export KUBECONFIG=/etc/kubernetes/admin.conf
# kubectl exec -n kube-system etcd-${CP0_HOSTNAME} -- etcdctl --ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key --endpoints=https://${CP0_IP}:2379 member add ${CP1_HOSTNAME} https://${CP1_IP}:2380
# kubeadm alpha phase etcd local --config kubeadm-config.yaml
//Master Node 2 를 Master Node 1 로 배포
# kubeadm alpha phase kubeconfig all --config kubeadm-config.yaml
# kubeadm alpha phase controlplane all --config kubeadm-config.yaml
# kubeadm alpha phase mark-master --config kubeadm-config.yaml |
결과)
● kubelet.service - kubelet: The Kubernetes Node Agent
Loaded: loaded (/etc/systemd/system/kubelet.service; enabled; vendor preset: disabled)
Drop-In: /etc/systemd/system/kubelet.service.d
└─10-kubeadm.conf
Active: active (running) since 월 2018-10-01 16:55:10 KST; 35s ago
Docs: https://kubernetes.io/docs/
Main PID: 16141 (kubelet)
Tasks: 26
Memory: 33.0M
CGroup: /system.slice/kubelet.service
└─16141 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/...
10월 01 16:55:45... kubelet[16141]: E1001 16:55:45.360340 16141 kubelet.go:2236] node "..." not found
10월 01 16:55:45... kubelet[16141]: E1001 16:55:45.460682 16141 kubelet.go:2236] node "..." not found
...
Hint: Some lines were ellipsized, use -l to show in full.
Master Node 3 Bootstrap
Master Node 3 Bootstrap 구성은 Master Node 2에서 진행했던 것과 동일하다.
| Code Block | ||
|---|---|---|
| ||
// 이동
mkdir -p /etc/kubernetes/pki/etcd
mv /root/ca.crt /etc/kubernetes/pki/
mv /root/ca.key /etc/kubernetes/pki/
mv /root/sa.pub /etc/kubernetes/pki/
mv /root/sa.key /etc/kubernetes/pki/
mv /root/front-proxy-ca.crt /etc/kubernetes/pki/
mv /root/front-proxy-ca.key /etc/kubernetes/pki/
mv /root/etcd-ca.crt /etc/kubernetes/pki/etcd/ca.crt
mv /root/etcd-ca.key /etc/kubernetes/pki/etcd/ca.key
mv /root/admin.conf /etc/kubernetes/admin.conf
# kubeadm alpha phase certs all --config kubeadm-config.yaml
# kubeadm alpha phase kubelet config write-to-disk --config kubeadm-config.yaml
# kubeadm alpha phase kubelet write-env-file --config kubeadm-config.yaml
# kubeadm alpha phase kubeconfig kubelet --config kubeadm-config.yaml
# systemctl start kubelet |
Master Node 3 Cluster
| Code Block | ||
|---|---|---|
| ||
# export CP0_IP={Master Node 1 IP}
# export CP0_HOSTNAME={Master Node 1 Host Name}
# export CP2_IP={Master Node 3 IP}
# export CP2_HOSTNAME={Master Node 3 Host Name}
# export KUBECONFIG=/etc/kubernetes/admin.conf# kubectl exec -n kube-system etcd-${CP0_HOSTNAME} -- etcdctl --ca-file /etc/kubernetes/pki/etcd/ca.crt --cert-file /etc/kubernetes/pki/etcd/peer.crt --key-file /etc/kubernetes/pki/etcd/peer.key --endpoints=https://${CP0_IP}:2379 member add ${CP2_HOSTNAME} https://${CP2_IP}:2380
# kubeadm alpha phase etcd local --config kubeadm-config.yaml
//Master Node 3 를 Master Node 1 로 배포
# kubeadm alpha phase kubeconfig all --config kubeadm-config.yaml
# kubeadm alpha phase controlplane all --config kubeadm-config.yaml
# kubeadm alpha phase mark-master --config kubeadm-config.yaml |
K8s Cluster Network Addon (only Master 1)
| Code Block | ||
|---|---|---|
| ||
// /proc/sys/net/bridge/bridge-nf-call-iptables 가 1로 셋팅되어 있는지 확인
# cat /proc/sys/net/bridge/bridge-nf-call-iptables
// 1이 아니면, 아래 명령어로 설정
# sysctl net.bridge.bridge-nf-call-iptables=1
# kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
# kubectl get nodes
NAME STATUS ROLES AGE VERSION
hostname Ready master 15h v1.11.2
hostname Ready master 15h v1.11.2
hostname Ready master 15h v1.11.2
# kubectl get pods --all-namespaces
kube-system coredns-78fcdf6894-969pp 1/1 Running 0 15h |
K8s Sub Node Join
| Code Block | ||
|---|---|---|
| ||
# echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
//변경확인
# cat /proc/sys/net/ipv4/ip_forward
# kubeadm join --token <token> <master-ip>:<master-port> --discovery-token-ca-cert-hash sha256:<hash> |
결과)
[preflight] running pre-flight checks
[WARNING RequiredIPVSKernelModulesAvailable]: the IPVS proxier will not be used, because the following required kernel modules are not loaded: [ip_vs ip_vs_rr ip_vs_wrr ip_vs_sh] or no builtin kernel ipvs support: map[ip_vs:{} ip_vs_rr:{} ip_vs_wrr:{} ip_vs_sh:{} nf_conntrack_ipv4:{}]
you can solve this problem with following methods:
1. Run 'modprobe -- ' to load missing kernel modules;
2. Provide the missing builtin kernel ipvs support
I1010 13:06:51.855190 19045 kernel_validator.go:81] Validating kernel version
I1010 13:06:51.855343 19045 kernel_validator.go:96] Validating kernel config
[discovery] Trying to connect to API Server...
[discovery] Created cluster-info discovery client, requesting info from...
[discovery] Requesting info from ... again to validate TLS against the pinned public key
[discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server...
[discovery] Successfully established connection with API Server ...
[kubelet] Downloading configuration for the kubelet from the "kubelet-config-1.11" ConfigMap in the kube-system namespace
[kubelet] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[preflight] Activating the kubelet service
[tlsbootstrap] Waiting for the kubelet to perform the TLS Bootstrap...
[patchnode] Uploading the CRI Socket information "/var/run/dockershim.sock" to the Node API object ... as an annotation
This node has joined the cluster:
* Certificate signing request was sent to master and a response
was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the master to see this node join the cluster.