├── docs ├── kthw.png ├── k8s-network.png ├── lab-00.md ├── lab-03.md ├── lab-09.md ├── lab-07.md ├── lab-08.md ├── lab-04.md ├── lab-06.md ├── prerequisites.md ├── lab-02.md ├── lab-01.md ├── lab-10.md └── lab-05.md ├── README.md └── LICENSE /docs/kthw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmyung/kubernetes-the-hard-way-modified/HEAD/docs/kthw.png -------------------------------------------------------------------------------- /docs/k8s-network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jmyung/kubernetes-the-hard-way-modified/HEAD/docs/k8s-network.png -------------------------------------------------------------------------------- /docs/lab-00.md: -------------------------------------------------------------------------------- 1 | # 시작하기 전에 2 | 3 | ## 쿠버네티스를 설치할 수 있는 수 많은 솔루션 4 | - 소개 : https://v1-13.docs.kubernetes.io/ko/docs/setup/pick-right-solution/ 5 | - 좀더 스마트하게 설치 가능 6 | - 매니지드 서비스 7 | 8 | ## 그럼에도 이 과정의 의미는? 9 | - 쿠버네티스 클러스터를 매뉴얼하게 설치해보면서, 구조를 이해해 봅니다. 10 | - 실제 자동화 설치 툴(ex : kubeadm)을 사용하다가 문제가 생겼을때, 원인을 파악해 볼 수 있습니다. 11 | -------------------------------------------------------------------------------- /docs/lab-03.md: -------------------------------------------------------------------------------- 1 | # LAB-03. 데이터 암호화 구성 및 키 생성 2 | 3 | 4 | Kubernetes는 클러스터 상태, 어플리케이션 구성 및 secret을 비롯한 다양한 데이터를 저장합니다. Kubernetes는 클러스터 데이터를 암호화하는 기능을 지원합니다. 5 | 6 | 이 랩에서는 Kubernetes Secrets 암호화에 적합한 암호화 키 및 암호화 구성을 생성합니다. 7 | 8 | ## 1. 암호화 키 생성 9 | 10 | ```sh 11 | ENCRYPTION_KEY=$(head -c 32 /dev/urandom | base64) 12 | ``` 13 | 14 | ## 2. encryption-config.yaml 생성 15 | 16 | ```yaml 17 | cat > encryption-config.yaml < 이 랩은 인증서를 생성했던 디렉토리에서 실행합니다. 6 | 7 | ## 1. Admin 쿠버네티스 구성 파일 생성 8 | 9 | 각 kubeconfig에는 쿠버네티스 API 서버가 연결되어 있어야 합니다. 고가용성을 지원하기 위해 로드밸런서에 할당된 IP 주소가 사용됩니다. 10 | 11 | `admin` 사용자용 컨텍스트 생성 12 | 13 | ```sh 14 | { 15 | KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \ 16 | --region $(gcloud config get-value compute/region) \ 17 | --format 'value(address)') 18 | 19 | kubectl config set-cluster kubernetes-the-hard-way \ 20 | --certificate-authority=ca.pem \ 21 | --embed-certs=true \ 22 | --server=https://${KUBERNETES_PUBLIC_ADDRESS}:6443 23 | 24 | kubectl config set-credentials admin \ 25 | --client-certificate=admin.pem \ 26 | --client-key=admin-key.pem 27 | 28 | kubectl config set-context kubernetes-the-hard-way \ 29 | --cluster=kubernetes-the-hard-way \ 30 | --user=admin 31 | 32 | kubectl config use-context kubernetes-the-hard-way 33 | } 34 | ``` 35 | 36 | ## 2. 확인 37 | 38 | 원격 쿠버네티스 클러스터의 상태 확인 39 | 40 | ```sh 41 | kubectl get componentstatuses 42 | ``` 43 | 44 | > 출력(예) 45 | 46 | ```sh 47 | NAME STATUS MESSAGE ERROR 48 | controller-manager Healthy ok 49 | scheduler Healthy ok 50 | etcd-0 Healthy {"health":"true"} 51 | etcd-1 Healthy {"health":"true"} 52 | ``` 53 | 54 | 원격 쿠버네티스 클러스터의 노드 목록 조회 55 | 56 | ```sh 57 | kubectl get nodes 58 | ``` 59 | 60 | > 출력(예) 61 | 62 | ```sh 63 | NAME STATUS ROLES AGE VERSION 64 | worker-0 NotReady 9m42s v1.12.0 65 | worker-1 NotReady 9m42s v1.12.0 66 | ``` 67 | -------------------------------------------------------------------------------- /docs/lab-08.md: -------------------------------------------------------------------------------- 1 | # LAB-08. 네트워킹 2 | 3 | - [쿠버네티스 네트워킹 모델](https://kubernetes.io/docs/concepts/cluster-administration/networking/) 4 | - 전체 클러스터를 위한 하나의 가상 네트워크 5 | - 각 파드에는 고유한 IP가 존재 6 | - 서비스는 파드와 다른 범위의 IP 대역을 가짐 7 | 8 | - 네트워크 구성 9 | ![architecture](k8s-network.png "architecture") 10 | 11 | - 클러스터 네트워크 아키텍쳐 12 | - 클러스터 CIDR : 클러스터 내 파드에 할당하는데 사용되는 IP 범위. 여기서는 [10.200.0.0/16](lab-05.md#2-3-쿠버네티스-controller-manager-구성하기) 13 | - 서비스 클러스터 IP 범위 : 서비스에 대한 IP 범위. 이것은 클러스터 CIDR와 중복되어서는 안됩니다. 여기서는 [10.32.0.0/24](lab-05.md#2-3-쿠버네티스-controller-manager-구성하기) 14 | - 파드(Pod) CIDR : 특정 워커 노드 내 파드에 대한 IP 범위. 이 범위는 클러스터 CIDR 내에 있어야 하지만, 다른 워커 노드의 파드 CIDR와 겹치지 않아야 합니다. 이 과정에서는 네트워킹 플러그인이 노드에 대한 IP 할당을 자동으로 처리하므로 파드 CIDR을 수동으로 설정할 필요가 없습니다. 15 | 16 | ## 1. 모든 워커 노드에서 IP forwarding 활성화 17 | 18 | ```sh 19 | sudo sysctl net.ipv4.conf.all.forwarding=1 20 | echo "net.ipv4.conf.all.forwarding=1" | sudo tee -a /etc/sysctl.conf 21 | ``` 22 | 23 | ## 2. 클러스터에 네트워킹 플러그인 (Weave Net) 설치 24 | 25 | Weaveworks를 사용하여 Weave Net 설치 26 | ```sh 27 | kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')&env.IPALLOC_RANGE=10.200.0.0/16" 28 | ``` 29 | 30 | 확인 31 | ```sh 32 | kubectl get pods -n kube-system 33 | ``` 34 | 35 | > 출력 (예) 36 | 37 | ``` 38 | NAME READY STATUS RESTARTS AGE 39 | weave-net-m69xq 2/2 Running 0 11s 40 | weave-net-vmb2n 2/2 Running 0 11s 41 | ``` 42 | 43 | ## 3. 네트워킹 기능을 테스트하기 위해 파드 실행 44 | 45 | ### 3-1. 디플로이먼트 생성 46 | 47 | 2개의 레플리카를 spec으로 하는 nginx 디플로이먼트 생성 48 | 49 | ```yaml 50 | cat << EOF | kubectl apply -f - 51 | apiVersion: apps/v1 52 | kind: Deployment 53 | metadata: 54 | name: nginx 55 | spec: 56 | selector: 57 | matchLabels: 58 | run: nginx 59 | replicas: 2 60 | template: 61 | metadata: 62 | labels: 63 | run: nginx 64 | spec: 65 | containers: 66 | - name: my-nginx 67 | image: nginx 68 | ports: 69 | - containerPort: 80 70 | EOF 71 | ``` 72 | 73 | ### 3-2. 서비스 생성 74 | 75 | 서비스에 대한 연결을 테스트 할 수 있도록 해당 디플로이먼트에 대한 서비스 생성 76 | 77 | ```sh 78 | kubectl expose deployment/nginx 79 | ``` 80 | 81 | ### 3-3. 테스트용 busybox 파드 실행 82 | 83 | 이 파드에서 다른 파드 및 서비스에 연결할 수 있는지 여부를 테스트합니다. 84 | 85 | ```sh 86 | kubectl run busybox --image=radial/busyboxplus:curl --command -- sleep 3600 87 | POD_NAME=$(kubectl get pods -l run=busybox -o jsonpath="{.items[0].metadata.name}") 88 | ``` 89 | 90 | ### 3-4. 테스트 91 | 92 | #### 3-4-1. 파드 (Pod) 테스트 93 | 94 | 두 개의 nginx 파드의 IP 주소 조회 95 | 96 | ``` 97 | kubectl get ep nginx 98 | ``` 99 | 100 | ``` 101 | NAME ENDPOINTS AGE 102 | nginx 10.200.0.2:80,10.200.128.1:80 50m 103 | ``` 104 | 105 | nginx 파드 테스트 106 | 107 | ```sh 108 | kubectl exec $POD_NAME -- curl <첫번째 nginx 파드 IP 주소> 109 | kubectl exec $POD_NAME -- curl <두번째 nginx 파드 IP 주소> 110 | ``` 111 | 112 | #### 3-4-2. 서비스 테스트 113 | 114 | 서비스 조회 115 | ```sh 116 | kubectl get svc 117 | ``` 118 | 119 | nginx 서비스 IP 주소 확인(예) 120 | ``` 121 | NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 122 | kubernetes ClusterIP 10.32.0.1 443/TCP 1h 123 | nginx ClusterIP 10.32.0.123 80/TCP 23m 124 | ``` 125 | 126 | nginx 서비스 테스트 127 | ```sh 128 | kubectl exec $POD_NAME -- curl 129 | ``` 130 | -------------------------------------------------------------------------------- /docs/lab-04.md: -------------------------------------------------------------------------------- 1 | # LAB-04. etcd 클러스터 부트스트래핑 2 | 3 | 쿠버네티스 컴포넌트는 stateless하고 [etcd](https://github.com/coreos/etcd)에 클러스터 상태를 저장합니다. 4 | 이 랩에서는 두 노드의 etcd 클러스터를 부트스트랩 합니다. 5 | 6 | - etcd 7 | - 기능 : 분산 시스템의 중요 데이터를 저장하기 위한 신뢰할 수 있는 key-value 저장소입니다. 8 | - 역할 : 클러스터 내 분산된 머신에 데이터를 저장하고, 모든 머신에서 데이터가 동기화되는지 확인하는 방법을 제공합니다. 9 | 10 | - 쿠버네티스 내에서 etcd 역할 11 | - 쿠버네티스는 etcd를 사용하여 클러스터 상태에 대한 모든 내부 데이터를 저장합니다. 12 | - 저장된 데이터는 클러스터의 모든 마스터 노드에서 안정적으로 동기화되어야 합니다. 13 | 14 | ## 1. 마스터 노드 접속 15 | 16 | 이 랩의 명령은 각 마스터 노드에서 실행해야합니다. : `controller-0`, `controller-1` 17 | 18 | ```sh 19 | gcloud compute ssh controller-0 20 | ``` 21 | 22 | ## 2. etcd 클러스터 멤버를 부트스트랩하기 23 | 24 | ### 2-1. etcd 다운로드 및 설치 25 | 26 | ```sh 27 | wget -q --show-progress --https-only --timestamping \ 28 | "https://github.com/coreos/etcd/releases/download/v3.3.9/etcd-v3.3.9-linux-amd64.tar.gz" 29 | ``` 30 | 31 | `etcd` 서버와 `etcdctl` 커맨드 라인 유틸리티 설치 32 | 33 | ``` 34 | { 35 | tar -xvf etcd-v3.3.9-linux-amd64.tar.gz 36 | sudo mv etcd-v3.3.9-linux-amd64/etcd* /usr/local/bin/ 37 | } 38 | ``` 39 | 40 | ### 2-2. `etcd` 서버 구성 41 | 42 | ``` 43 | { 44 | sudo mkdir -p /etc/etcd /var/lib/etcd 45 | sudo cp ca.pem kubernetes-key.pem kubernetes.pem /etc/etcd/ 46 | } 47 | ``` 48 | 49 | VM 인스턴스 내부 IP 주소는 클라이언트 요청을 처리하고 etcd 클러스터 peer와 통신하는데 사용됩니다. 50 | 51 | VM 인스턴스 내부 IP 주소 조회 52 | ``` 53 | INTERNAL_IP=$(curl -s -H "Metadata-Flavor: Google" \ 54 | http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip) 55 | ``` 56 | 57 | > (AWS 인 경우) INTERNAL_IP=$(curl http://169.254.169.254/latest/meta-data/local-ipv4) 58 | 59 | 60 | 각 etcd 멤버는 etcd 클러스터 내에서 고유한 이름을 가져야합니다. 현재 VM의 호스트 이름과 일치하도록 etcd 이름을 설정합니다. 61 | 62 | ``` 63 | ETCD_NAME=$(hostname -s) 64 | ``` 65 | 66 | INITIAL_CLUSTER에 etcd 클러스터의 모든 서버 리스트를 설정합니다. 67 | 68 | ```sh 69 | INITIAL_CLUSTER=controller-0=https://10.240.0.10:2380,controller-1=https://10.240.0.11:2380 70 | ``` 71 | 72 | `etcd.service` systemd 유닛 파일 생성 73 | 74 | ``` 75 | cat < 각 마스터 노드에서 위의 명령을 실행합니다 : `controller-0`,`controller-1` 118 | 119 | ## 3. 확인 120 | 121 | etcd 클러스터 멤버 조회 122 | 123 | ``` 124 | sudo ETCDCTL_API=3 etcdctl member list \ 125 | --endpoints=https://127.0.0.1:2379 \ 126 | --cacert=/etc/etcd/ca.pem \ 127 | --cert=/etc/etcd/kubernetes.pem \ 128 | --key=/etc/etcd/kubernetes-key.pem 129 | ``` 130 | 131 | > 출력 예 132 | 133 | ``` 134 | 3a57933972cb5131, started, controller-0, https://10.240.0.12:2380, https://10.240.0.12:2379 135 | f98dc20bce6225a0, started, controller-1, https://10.240.0.10:2380, https://10.240.0.10:2379 136 | ``` 137 | -------------------------------------------------------------------------------- /docs/lab-06.md: -------------------------------------------------------------------------------- 1 | # LAB-06. Kubernetes Worker Nodes 부트스트래핑 2 | 3 | - 워커 노드 (Worker Nodes) : 쿠버네티스에서 관리하는 컨테이너 어플리케이션의 실제 작업을 담당합니다. 4 | - 이 랩에서는 두 개의 워커 노드를 부트스트랩 합니다. 5 | - 컨트롤 플레인 컴포넌트 (워커 노드) 6 | - **[kubelet](https://kubernetes.io/docs/admin/kubelet)** : 워커 노드에서 실행되는 에이전트. Kubelet은 파드 스펙(PodSpec)을 받아, 파드에서 컨테이너가 동작하도록 관리합니다. 7 | - **[kube-proxy](https://kubernetes.io/docs/concepts/cluster-administration/proxies)** : 워커 노드에서 실행되는 네트워크 프록시로서, 호스트의 네트워크 규칙(iptables)을 관리하고 요청에 대한 포워딩을 책임집니다. (NodePort로 들어온 트래픽을 클러스터 내의 적절한 파드로 리다이렉팅) 8 | - **컨테이너 런타임** : 컨테이너 실행을 담당하는 소프트웨어 9 | 10 | 11 | - 다음 구성 요소가 각 노드에 설치됩니다. 12 | - kubelet 13 | - kube-proxy 14 | - docker 15 | - ~~[runc](https://github.com/opencontainers/runc)~~ 16 | - ~~[containerd](https://github.com/containerd/containerd)~~ 17 | - ~~[container networking plugins](https://github.com/containernetworking/cni)~~ 18 | - [gVisor](https://github.com/google/gvisor) 19 | 20 | - 아키텍쳐 21 | ![architecture](kthw.png "architecture") 22 | 23 | 24 | ## 1. 준비 사항 25 | 26 | 이 랩에서 명령은 워커 노드인 `worker-0`,`worker-1` 모두 에서 실행되어야 합니다. 27 | 28 | GCP 인스턴스 ssh 로그인 29 | ``` 30 | gcloud compute ssh worker-0 31 | ``` 32 | 33 | ## 2. 쿠버네티스 워커 노드 프로비저닝 34 | 35 | OS dependencies 설치 36 | 37 | ```sh 38 | { 39 | sudo apt-get update 40 | sudo apt-get -y install socat conntrack ipset 41 | } 42 | ``` 43 | 44 | > socat 바이너리는 `kubectl port-forward` 명령을 지원합니다. 45 | 46 | 47 | ### 2-1. 쿠버네티스 워커 바이너리 다운로드 및 설치 48 | 49 | ```sh 50 | wget -q --show-progress --https-only --timestamping \ 51 | https://github.com/containernetworking/plugins/releases/download/v0.6.0/cni-plugins-amd64-v0.6.0.tgz \ 52 | https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kubectl \ 53 | https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kube-proxy \ 54 | https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kubelet 55 | ``` 56 | 57 | 58 | 설치 디렉토리 생성 59 | 60 | ```sh 61 | sudo mkdir -p \ 62 | /opt/cni/bin/ \ 63 | /var/lib/kubelet \ 64 | /var/lib/kube-proxy \ 65 | /var/lib/kubernetes \ 66 | /var/run/kubernetes 67 | ``` 68 | 69 | 워커 바이너리 설치 70 | 71 | ```sh 72 | { 73 | chmod +x kubectl kube-proxy kubelet 74 | sudo mv kubectl kube-proxy kubelet /usr/local/bin 75 | sudo tar -xvf cni-plugins-amd64-v0.6.0.tgz -C /opt/cni/bin/ 76 | } 77 | ``` 78 | 79 | 도커 설치 80 | ```sh 81 | sudo apt install docker.io -y 82 | ``` 83 | 84 | ### 2-2. Kubelet 구성 85 | 86 | ```sh 87 | { 88 | sudo mv ${HOSTNAME}-key.pem ${HOSTNAME}.pem /var/lib/kubelet/ 89 | sudo mv ${HOSTNAME}.kubeconfig /var/lib/kubelet/kubeconfig 90 | sudo mv ca.pem /var/lib/kubernetes/ 91 | } 92 | ``` 93 | 94 | `kubelet-config.yaml` 설정 파일 생성 95 | 96 | ```yaml 97 | cat << EOF | sudo tee /var/lib/kubelet/kubelet-config.yaml 98 | kind: KubeletConfiguration 99 | apiVersion: kubelet.config.k8s.io/v1beta1 100 | authentication: 101 | anonymous: 102 | enabled: false 103 | webhook: 104 | enabled: true 105 | x509: 106 | clientCAFile: "/var/lib/kubernetes/ca.pem" 107 | authorization: 108 | mode: Webhook 109 | clusterDomain: "cluster.local" 110 | clusterDNS: 111 | - "10.32.0.10" 112 | runtimeRequestTimeout: "15m" 113 | tlsCertFile: "/var/lib/kubelet/${HOSTNAME}.pem" 114 | tlsPrivateKeyFile: "/var/lib/kubelet/${HOSTNAME}-key.pem" 115 | EOF 116 | ``` 117 | 118 | `kubelet.service` systemd 파일 생성 119 | 120 | ```sh 121 | cat < kubelet이 hostname을 제대로 못가져 오는 경우, --hostname-override=${HOSTNAME}, --allow-privileged=true 를 사용해야할 수 도 있습니다. 146 | 147 | ### 2-3. 쿠버네티스 Proxy 구성 148 | 149 | ``` 150 | sudo mv kube-proxy.kubeconfig /var/lib/kube-proxy/kubeconfig 151 | ``` 152 | 153 | `kube-proxy-config.yaml` 설정 파일 생성 154 | 155 | ```yaml 156 | cat < 각 워커 노드에서 위의 명령들을 실행해야합니다 : `worker-0`,`worker-1` 203 | 204 | ## 3. 확인 205 | 206 | > 워커 노드 인스턴스에서는 다음 명령을 수행할 수 있는 권한이 없습니다. 마스터 노드에서 다음 명령을 실행합니다. 207 | 208 | 등록된 Kubernetes 노드를 조회 209 | 210 | ``` 211 | gcloud compute ssh controller-0 \ 212 | --command "kubectl get nodes --kubeconfig admin.kubeconfig" 213 | ``` 214 | 215 | > 출력 216 | 217 | ``` 218 | NAME STATUS ROLES AGE VERSION 219 | worker-0 NotReady 103s v1.12.0 220 | worker-1 NotReady 103s v1.12.0 221 | ``` 222 | 223 | - 네트워크 설정이 아직 남아있기 때문에, `NotReady` 상태입니다. 224 | -------------------------------------------------------------------------------- /docs/prerequisites.md: -------------------------------------------------------------------------------- 1 | # 사전 준비 2 | 3 | - 실습 간 슬랙을 활용합니다. 4 | - 가입링크 : http://34.94.33.120/ 를 클릭하여 이메일을 기재하시면 초대메일이 발송됩니다. 5 | - 슬랙 주소 : https://peanut-butter-group.slack.com 6 | - Channels > `#k8s-the-hard-way` 채널 조인 7 | - 참석 전에 반드시, 쿠버네티스 클러스터를 설치할 VM을 미리 구성해주시기 바랍니다. 8 | - 이하 절차 수행 9 | - 문의 사항은 슬랙에 올려주세요. 10 | 11 | ## 1. GCP (Google Cloud Platform) 가입 12 | 13 | - 사이트 가입 : https://console.cloud.google.com/ 14 | - 필요 사항 : 해외 결제 가능한 신용 카드 등록 15 | - 본 가이드는 1년간 무료로 주어지는 $300 크래딧 내에서 진행합니다. 16 | - AWS에서 VM을 띄우셔도 상관없습니다. 단 [방화벽 작업](https://github.com/jmyung/kubernetes-the-hard-way-modified/blob/master/docs/prerequisites.md#vpc-%EC%83%9D%EC%84%B1-%EC%84%9C%EB%B8%8C%EB%84%B7-%EC%83%9D%EC%84%B1-%EB%B0%A9%ED%99%94%EB%B2%BD-%ED%95%B4%EC%A0%9C)은 이하 내용을 참고하여 해제해주세요. 17 | 18 | 19 | ## 2. VM 띄우기 20 | 21 | ### 2-1. 프로젝트 생성 22 | 23 | - Select a project > New Project 24 | - `Project name` 기입 후 `CREATE` 버튼 클릭 25 | - `Cloud Shell` 버튼 클릭하여 이하 진행 (https://cloud.google.com/shell/) 26 | - 프로젝트ID 확인 (기입한 프로젝트명과 다를 수 있음) 27 | 28 | ### 2-2. 리전 설정 및 GCP API 활성화 29 | 30 | - 프로젝트ID 변수화 31 | ```sh 32 | PROJECT_ID="프로젝트ID" 33 | ``` 34 | 35 | - 리전 설정 및 GCP API 활성화 36 | ```sh 37 | { 38 | gcloud config set project ${PROJECT_ID} 39 | gcloud config set compute/region us-west2 40 | gcloud config set compute/zone us-west2-c 41 | gcloud services enable compute.googleapis.com 42 | } 43 | ``` 44 | 45 | - config-update.sh 46 | ```sh 47 | mkdir setup 48 | cd setup 49 | vi config-update.sh 50 | ``` 51 | 52 | ```sh 53 | PROJECT_ID="프로젝트ID" 54 | gcloud config set project ${PROJECT_ID} 55 | gcloud config set compute/region us-west2 56 | gcloud config set compute/zone us-west2-c 57 | ``` 58 | 저장후 59 | ``` 60 | chmod +x config-update.sh 61 | ``` 62 | 63 | ### 2-3. VM 생성 64 | 65 | #### 2-3-1. 네트워크 생성 66 | 67 | ##### VPC 생성, 서브넷 생성, 방화벽 해제 68 | ```sh 69 | { 70 | gcloud compute networks create kubernetes-the-hard-way --subnet-mode custom 71 | gcloud compute networks subnets create kubernetes \ 72 | --network kubernetes-the-hard-way \ 73 | --range 10.240.0.0/24 74 | gcloud compute firewall-rules create kubernetes-the-hard-way-allow-internal \ 75 | --allow tcp,udp,icmp \ 76 | --network kubernetes-the-hard-way \ 77 | --source-ranges 10.240.0.0/24,10.200.0.0/16 78 | gcloud compute firewall-rules create kubernetes-the-hard-way-allow-external \ 79 | --allow tcp:22,tcp:6443,icmp \ 80 | --network kubernetes-the-hard-way \ 81 | --source-ranges 0.0.0.0/0 82 | } 83 | ``` 84 | 85 | ##### 확인 86 | 87 | ```sh 88 | gcloud compute firewall-rules list --filter="network:kubernetes-the-hard-way" 89 | ``` 90 | 91 | 92 | 93 | #### 2-3-2. 마스터 VM 생성 94 | 95 | ```sh 96 | for i in 0 1; do 97 | gcloud compute instances create controller-${i} \ 98 | --async \ 99 | --boot-disk-size 10GB \ 100 | --can-ip-forward \ 101 | --image-family ubuntu-1804-lts \ 102 | --image-project ubuntu-os-cloud \ 103 | --machine-type n1-standard-1 \ 104 | --private-network-ip 10.240.0.1${i} \ 105 | --scopes compute-rw,storage-ro,service-management,service-control,logging-write,monitoring \ 106 | --subnet kubernetes \ 107 | --tags kubernetes-the-hard-way,controller 108 | done 109 | ``` 110 | 111 | #### 2-3-3. 워커 VM 생성 112 | 113 | ```sh 114 | for i in 0 1; do 115 | gcloud compute instances create worker-${i} \ 116 | --async \ 117 | --boot-disk-size 10GB \ 118 | --can-ip-forward \ 119 | --image-family ubuntu-1804-lts \ 120 | --image-project ubuntu-os-cloud \ 121 | --machine-type n1-standard-1 \ 122 | --metadata pod-cidr=10.200.${i}.0/24 \ 123 | --private-network-ip 10.240.0.2${i} \ 124 | --scopes compute-rw,storage-ro,service-management,service-control,logging-write,monitoring \ 125 | --subnet kubernetes \ 126 | --tags kubernetes-the-hard-way,worker 127 | done 128 | ``` 129 | 130 | #### 2-3-4. 로드밸런서 VM 생성 131 | - VM 생성 132 | ```sh 133 | gcloud compute instances create load-balancer \ 134 | --async \ 135 | --boot-disk-size 10GB \ 136 | --can-ip-forward \ 137 | --image-family ubuntu-1804-lts \ 138 | --image-project ubuntu-os-cloud \ 139 | --machine-type n1-standard-1 \ 140 | --private-network-ip 10.240.0.30 \ 141 | --scopes compute-rw,storage-ro,service-management,service-control,logging-write,monitoring \ 142 | --subnet kubernetes \ 143 | --tags kubernetes-the-hard-way,load-balancer 144 | ``` 145 | - 정적 Public IP 생성 146 | ```sh 147 | gcloud compute addresses create kubernetes-the-hard-way \ 148 | --region $(gcloud config get-value compute/region) 149 | ``` 150 | - IP 확인 151 | ```sh 152 | gcloud compute addresses list --filter="name=('kubernetes-the-hard-way')" 153 | ``` 154 | - 정적 IP를 로드밸런서 VM에 붙이기 155 | ```sh 156 | gcloud compute instances delete-access-config load-balancer --access-config-name "external-nat" 157 | gcloud compute instances add-access-config load-balancer --access-config-name "external-nat" --address [바로위에 확인된 IP 기입] 158 | ``` 159 | 160 | #### 2-3-4. 확인 161 | ```sh 162 | gcloud compute instances list 163 | ``` 164 | 165 | ### 2-9. 자주쓰는 쉘 만들어놓기 (필수 아님) 166 | - start.sh 167 | ```sh 168 | for instance in controller-0 controller-1 load-balancer worker-0 worker-1 ; do 169 | gcloud compute instances start ${instance} 170 | done 171 | ``` 172 | 173 | - stop.sh 174 | ```sh 175 | for instance in controller-0 controller-1 load-balancer worker-0 worker-1 ; do 176 | gcloud compute instances stop ${instance} 177 | done 178 | ``` 179 | 180 | - init.sh 181 | ```sh 182 | gcloud config set project {프로젝트명} 183 | gcloud config set compute/region us-west2 184 | gcloud config set compute/zone us-west2-c 185 | wget -q --show-progress --https-only --timestamping \ 186 | https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 \ 187 | https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 188 | chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 189 | sudo mv cfssl_linux-amd64 /usr/local/bin/cfssl 190 | sudo mv cfssljson_linux-amd64 /usr/local/bin/cfssljson 191 | ./start.sh 192 | ``` 193 | 194 | - CLEAN UP 195 | - 방법1 196 | ```sh 197 | for instance in controller-0 controller-1 load-balancer worker-0 worker-1 ; do 198 | gcloud compute instances delete ${instance} 199 | done 200 | ``` 201 | ```sh 202 | gcloud compute addresses delete kubernetes-the-hard-way \ 203 | --region $(gcloud config get-value compute/region) 204 | ``` 205 | - 방법2 : 콘솔에서 프로젝트를 delete 하면 생성한 자원들이 모두 삭제됩니다. 206 | -------------------------------------------------------------------------------- /docs/lab-02.md: -------------------------------------------------------------------------------- 1 | # LAB-02. 인증을 위한 Kubernetes config 파일 생성 2 | 3 | - 이 랩에서는 `kubeconfig`이라 불리는, [Kubernetes 설정 파일](https://kubernetes.io/docs/concepts/configuration/organize-cluster-access-kubeconfig/)을 생성합니다. 4 | - kubeconfig는 Kubernetes 클라이언트가 Kubernetes API 서버를 찾고 인증 할 수 있도록 해줍니다. 5 | 6 | ## 1. 클라이언트 인증 구성 7 | 8 | 이 섹션에서는 이하의 kubeconfig 파일을 생성합니다. 9 | - 워커 노드 용 10 | - `kubelet` 11 | - `kube-proxy` 12 | - 마스터 노드 용 13 | - `kube-controller-manager` 14 | - `kube-scheduler` 클라이언트 15 | - `admin` 사용자 16 | 17 | > 위 쿠버네티스 컴포넌트에 대한 설명은 [이곳](https://kubernetes.io/ko/docs/concepts/overview/components/)을 참고하세요. 18 | 19 | ### 1-1. kubeconfig 해부 20 | 21 | - kubectl config set-cluster : 클러스터 위치에 대한 구성을 설정 22 | - kubectl config set-credentials : 인증에 사용되는 사용자 이름 및 클라이언트 인증서를 설정 23 | - kubectl config set-context default : 디폴트 컨텍스트를 설정 24 | - kubectl config use-context default : 위 구성으로 현재 컨텍스트를 설정 25 | 26 | ### 1-2. 정적 Public IP 조회 27 | 28 | ```sh 29 | KUBERNETES_PUBLIC_ADDRESS=$(gcloud compute addresses describe kubernetes-the-hard-way \ 30 | --region $(gcloud config get-value compute/region) \ 31 | --format 'value(address)') 32 | ``` 33 | 34 | ### 1-3. kubelet kubeconfig 생성 35 | 36 | Kubelet kubeconfig 파일을 생성할 때 Kubelet의 노드 이름과 일치하는 클라이언트 인증서를 사용해야합니다. 이렇게 하면 Kuubenetes Node Authorizer가 Kubelet을 올바르게 인증할 수 있습니다. 37 | 38 | 각 워커 노드에 대해 kubeconfig 파일 생성 39 | 40 | ```sh 41 | for instance in worker-0 worker-1; do 42 | kubectl config set-cluster kubernetes-the-hard-way \ 43 | --certificate-authority=ca.pem \ 44 | --embed-certs=true \ 45 | --server=https://${KUBERNETES_PUBLIC_ADDRESS}:6443 \ 46 | --kubeconfig=${instance}.kubeconfig 47 | 48 | kubectl config set-credentials system:node:${instance} \ 49 | --client-certificate=${instance}.pem \ 50 | --client-key=${instance}-key.pem \ 51 | --embed-certs=true \ 52 | --kubeconfig=${instance}.kubeconfig 53 | 54 | kubectl config set-context default \ 55 | --cluster=kubernetes-the-hard-way \ 56 | --user=system:node:${instance} \ 57 | --kubeconfig=${instance}.kubeconfig 58 | 59 | kubectl config use-context default --kubeconfig=${instance}.kubeconfig 60 | done 61 | ``` 62 | 63 | 결과 64 | ``` 65 | worker-0.kubeconfig 66 | worker-1.kubeconfig 67 | ``` 68 | 69 | ### 1-4. kube-proxy kubeconfig 생성 70 | 71 | `kube-proxy` 서비스에 대해 kubeconfig 파일 생성 72 | 73 | ```sh 74 | { 75 | kubectl config set-cluster kubernetes-the-hard-way \ 76 | --certificate-authority=ca.pem \ 77 | --embed-certs=true \ 78 | --server=https://${KUBERNETES_PUBLIC_ADDRESS}:6443 \ 79 | --kubeconfig=kube-proxy.kubeconfig 80 | 81 | kubectl config set-credentials system:kube-proxy \ 82 | --client-certificate=kube-proxy.pem \ 83 | --client-key=kube-proxy-key.pem \ 84 | --embed-certs=true \ 85 | --kubeconfig=kube-proxy.kubeconfig 86 | 87 | kubectl config set-context default \ 88 | --cluster=kubernetes-the-hard-way \ 89 | --user=system:kube-proxy \ 90 | --kubeconfig=kube-proxy.kubeconfig 91 | 92 | kubectl config use-context default --kubeconfig=kube-proxy.kubeconfig 93 | } 94 | ``` 95 | 96 | 결과 97 | ``` 98 | kube-proxy.kubeconfig 99 | ``` 100 | 101 | ### 1-5. kube-controller-manager kubeconfig 생성 102 | 103 | `kube-controller-manager` 서비스에 대해 kubeconfig 파일 생성 104 | 105 | ```sh 106 | { 107 | kubectl config set-cluster kubernetes-the-hard-way \ 108 | --certificate-authority=ca.pem \ 109 | --embed-certs=true \ 110 | --server=https://127.0.0.1:6443 \ 111 | --kubeconfig=kube-controller-manager.kubeconfig 112 | 113 | kubectl config set-credentials system:kube-controller-manager \ 114 | --client-certificate=kube-controller-manager.pem \ 115 | --client-key=kube-controller-manager-key.pem \ 116 | --embed-certs=true \ 117 | --kubeconfig=kube-controller-manager.kubeconfig 118 | 119 | kubectl config set-context default \ 120 | --cluster=kubernetes-the-hard-way \ 121 | --user=system:kube-controller-manager \ 122 | --kubeconfig=kube-controller-manager.kubeconfig 123 | 124 | kubectl config use-context default --kubeconfig=kube-controller-manager.kubeconfig 125 | } 126 | ``` 127 | 128 | 결과 129 | ``` 130 | kube-controller-manager.kubeconfig 131 | ``` 132 | 133 | ### 1-6. kube-scheduler kubeconfig 생성 134 | 135 | `kube-scheduler` 서비스에 대해 kubeconfig 파일 생성 136 | 137 | ```sh 138 | { 139 | kubectl config set-cluster kubernetes-the-hard-way \ 140 | --certificate-authority=ca.pem \ 141 | --embed-certs=true \ 142 | --server=https://127.0.0.1:6443 \ 143 | --kubeconfig=kube-scheduler.kubeconfig 144 | 145 | kubectl config set-credentials system:kube-scheduler \ 146 | --client-certificate=kube-scheduler.pem \ 147 | --client-key=kube-scheduler-key.pem \ 148 | --embed-certs=true \ 149 | --kubeconfig=kube-scheduler.kubeconfig 150 | 151 | kubectl config set-context default \ 152 | --cluster=kubernetes-the-hard-way \ 153 | --user=system:kube-scheduler \ 154 | --kubeconfig=kube-scheduler.kubeconfig 155 | 156 | kubectl config use-context default --kubeconfig=kube-scheduler.kubeconfig 157 | } 158 | ``` 159 | 160 | 결과 161 | ``` 162 | kube-scheduler.kubeconfig 163 | ``` 164 | 165 | ### 1-7. admin kubeconfig 생성 166 | 167 | `admin` 사용자에 대해 kubeconfig 파일 생성 168 | 169 | ```sh 170 | { 171 | kubectl config set-cluster kubernetes-the-hard-way \ 172 | --certificate-authority=ca.pem \ 173 | --embed-certs=true \ 174 | --server=https://127.0.0.1:6443 \ 175 | --kubeconfig=admin.kubeconfig 176 | 177 | kubectl config set-credentials admin \ 178 | --client-certificate=admin.pem \ 179 | --client-key=admin-key.pem \ 180 | --embed-certs=true \ 181 | --kubeconfig=admin.kubeconfig 182 | 183 | kubectl config set-context default \ 184 | --cluster=kubernetes-the-hard-way \ 185 | --user=admin \ 186 | --kubeconfig=admin.kubeconfig 187 | 188 | kubectl config use-context default --kubeconfig=admin.kubeconfig 189 | } 190 | ``` 191 | 192 | 결과 193 | ``` 194 | admin.kubeconfig 195 | ``` 196 | 197 | ## 2. kubeconfig 파일 배포 198 | 199 | `kubelet` 및 `kube-proxy` kubeconfig 파일을 각 워커 노드에 복사합니다. 200 | 201 | ```sh 202 | for instance in worker-0 worker-1; do 203 | gcloud compute scp ${instance}.kubeconfig kube-proxy.kubeconfig ${instance}:~/ 204 | done 205 | ``` 206 | 207 | `kube-controller-manage`, `kube-scheduler`, `admin` 사용자 kubeconfig 파일을 각 마스터 노드에 복사합니다. 208 | 209 | ```sh 210 | for instance in controller-0 controller-1; do 211 | gcloud compute scp admin.kubeconfig kube-controller-manager.kubeconfig kube-scheduler.kubeconfig ${instance}:~/ 212 | done 213 | ``` 214 | -------------------------------------------------------------------------------- /docs/lab-01.md: -------------------------------------------------------------------------------- 1 | # LAB-01. CA 프로비저닝 및 TLS 인증서 생성 2 | 3 | - 이 랩에서는 CloudFlare의 PKI 툴킷인 cfssl을 사용하여 PKI 인프라를 구축한 다음 4 | - 이를 사용하여 CA(인증 기관)을 부트스트랩하고, 5 | - etcd, kube-apiserver, kube-controller-manager, kube-scheduler, kubelet, kube-proxy 구성 요소에 대한 TLS 인증서를 생성합니다. 6 | 7 | ## 1. CFSSL 설치 8 | 9 | ```sh 10 | { 11 | wget -q --show-progress --https-only --timestamping \ 12 | https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 \ 13 | https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 14 | chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 15 | sudo mv cfssl_linux-amd64 /usr/local/bin/cfssl 16 | sudo mv cfssljson_linux-amd64 /usr/local/bin/cfssljson 17 | } 18 | ``` 19 | 20 | ## 2. CA 프로비저닝 21 | 22 | ```sh 23 | { 24 | 25 | cat > ca-config.json < ca-csr.json < admin-csr.json <`이라는 username으로 `system:nodes` 그룹에 있는 것으로 식별하는 credential을 사용해야합니다. 129 | - 이 섹션에서는 노드 인증 요구 사항을 충족하는 각 Kubernetes 워커 노드에 대한 인증서를 만듭니다. 130 | 131 | API 서버에서 kubelet과 통신을 위한 클라이언트 인증서 132 | 133 | ```sh 134 | for instance in worker-0 worker-1; do 135 | cat > ${instance}-csr.json < kube-controller-manager-csr.json < kube-proxy-csr.json < kube-scheduler-csr.json < kubernetes-csr.json < service-account-csr.json < 다음 랩에서는 `kube-proxy`, `kube-controller-manager`, `kube-scheduler`, `kubelet` 클라이언트 인증서를 사용하여 Kubernetes 설정 파일(kubeconfig)을 생성합니다. 415 | -------------------------------------------------------------------------------- /docs/lab-10.md: -------------------------------------------------------------------------------- 1 | # LAB-10. 스모크 테스트 2 | 3 | 이 실습에서는 쿠버네티스 클러스터가 올바르게 작동하는지 확인하기 위해 테스트 해봅니다. 4 | 5 | ## 1. 데이터 암호화 6 | 7 | 이 섹션에서는, [시크릿 데이터](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/#verifying-that-data-is-encrypted)를 암호화하는 기능을 확인합니다. 8 | 9 | generic secret 오브젝트 생성 10 | 11 | ```sh 12 | kubectl create secret generic kubernetes-the-hard-way \ 13 | --from-literal="mykey=mydata" 14 | ``` 15 | 16 | etcd에 저장된 kubernetes-the-hard-way secret의 hexdump를 출력합니다. 17 | 18 | ``` 19 | gcloud compute ssh controller-0 \ 20 | --command "sudo ETCDCTL_API=3 etcdctl get \ 21 | --endpoints=https://127.0.0.1:2379 \ 22 | --cacert=/etc/etcd/ca.pem \ 23 | --cert=/etc/etcd/kubernetes.pem \ 24 | --key=/etc/etcd/kubernetes-key.pem\ 25 | /registry/secrets/default/kubernetes-the-hard-way | hexdump -C" 26 | ``` 27 | 28 | > 출력 29 | 30 | ``` 31 | 00000000 2f 72 65 67 69 73 74 72 79 2f 73 65 63 72 65 74 |/registry/secret| 32 | 00000010 73 2f 64 65 66 61 75 6c 74 2f 6b 75 62 65 72 6e |s/default/kubern| 33 | 00000020 65 74 65 73 2d 74 68 65 2d 68 61 72 64 2d 77 61 |etes-the-hard-wa| 34 | 00000030 79 0a 6b 38 73 3a 65 6e 63 3a 61 65 73 63 62 63 |y.k8s:enc:aescbc| 35 | 00000040 3a 76 31 3a 6b 65 79 31 3a dd 3f 36 6c ce 65 9d |:v1:key1:.?6l.e.| 36 | 00000050 b3 b1 46 1a ba ae a2 1f e4 fa 13 0c 4b 6e 2c 3c |..F.........Kn,<| 37 | 00000060 15 fa 88 56 84 b7 aa c0 7a ca 66 f3 de db 2b a3 |...V....z.f...+.| 38 | 00000070 88 dc b1 b1 d8 2f 16 3e 6b 4a cb ac 88 5d 23 2d |...../.>kJ...]#-| 39 | 00000080 99 62 be 72 9f a5 01 38 15 c4 43 ac 38 5f ef 88 |.b.r...8..C.8_..| 40 | 00000090 3b 88 c1 e6 b6 06 4f ae a8 6b c8 40 70 ac 0a d3 |;.....O..k.@p...| 41 | 000000a0 3e dc 2b b6 0f 01 b6 8b e2 21 29 4d 32 d6 67 a6 |>.+......!)M2.g.| 42 | 000000b0 4e 6d bb 61 0d 85 22 ea f4 d6 2d 0a af 3c 71 85 |Nm.a.."...-.. 출력 68 | 69 | ``` 70 | NAME READY STATUS RESTARTS AGE 71 | nginx-dbddb74b8-6lxg2 1/1 Running 0 10s 72 | ``` 73 | 74 | ### 포트 포워딩 75 | 76 | 이 섹션에서는 [포트 포워딩](https://kubernetes.io/docs/tasks/access-application-cluster/port-forward-access-application-cluster/)을 사용하여 원격으로 어플리케이션에 액세스하는 기능을 확인합니다. 77 | 78 | 79 | `nginx` 파드 이름을 변수에 할당 80 | 81 | ``` 82 | POD_NAME=$(kubectl get pods -l run=nginx -o jsonpath="{.items[0].metadata.name}") 83 | ``` 84 | 85 | 로컬 머신의 `8080` 포트를 `nginx` 파드의 `80` 포트로 포워딩합니다. 86 | 87 | ``` 88 | kubectl port-forward $POD_NAME 8080:80 89 | ``` 90 | 91 | > 출력 92 | 93 | ``` 94 | Forwarding from 127.0.0.1:8080 -> 80 95 | Forwarding from [::1]:8080 -> 80 96 | ``` 97 | 98 | 새로운 터미널 창에서 포워딩 주소를 사용하여 HTTP 요청합니다. 99 | 100 | ``` 101 | curl --head http://127.0.0.1:8080 102 | ``` 103 | 104 | > 출력 105 | 106 | ``` 107 | HTTP/1.1 200 OK 108 | Server: nginx/1.15.4 109 | Date: Sun, 30 Sep 2018 19:23:10 GMT 110 | Content-Type: text/html 111 | Content-Length: 612 112 | Last-Modified: Tue, 25 Sep 2018 15:04:03 GMT 113 | Connection: keep-alive 114 | ETag: "5baa4e63-264" 115 | Accept-Ranges: bytes 116 | ``` 117 | 118 | 이전 터미널로 다시 전환하고 `nginx` 파드로 포트 포워딩을 중지합니다. 119 | 120 | ``` 121 | Forwarding from 127.0.0.1:8080 -> 80 122 | Forwarding from [::1]:8080 -> 80 123 | Handling connection for 8080 124 | ^C 125 | ``` 126 | 127 | ### 로그 128 | 129 | 이 섹션에서는 [컨테이너 로그를 검색](https://kubernetes.io/docs/concepts/cluster-administration/logging/)하는 기능을 확인합니다. 130 | 131 | `nginx` 파드 로그를 출력합니다. 132 | 133 | ``` 134 | kubectl logs $POD_NAME 135 | ``` 136 | 137 | > 출력 138 | 139 | ``` 140 | 127.0.0.1 - - [30/Sep/2018:19:23:10 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.58.0" "-" 141 | ``` 142 | 143 | ### 실행 (Exec) 144 | 145 | 이 섹션에서는 [컨테이너에서 명령을 실행](https://kubernetes.io/docs/tasks/debug-application-cluster/get-shell-running-container/#running-individual-commands-in-a-container)할 수 있는지 확인합니다. 146 | 147 | `nginx` 컨테이너에서 `nginx -v` 명령을 실행하여 nginx 버전을 출력합니다. 148 | 149 | ``` 150 | kubectl exec -ti $POD_NAME -- nginx -v 151 | ``` 152 | 153 | > 출력 154 | 155 | ``` 156 | nginx version: nginx/1.15.4 157 | ``` 158 | 159 | ## 서비스 160 | 161 | 이 섹션에서는 [서비스](https://kubernetes.io/docs/concepts/services-networking/service/)를 사용하여 어플리케이션을 노출하는 기능을 확인합니다. 162 | 163 | ```sh 164 | kubectl expose deployment nginx --port 80 --type NodePort 165 | ``` 166 | 167 | > 클러스터가 [클라우드 공급자 통합](https://kubernetes.io/docs/getting-started-guides/scratch/#cloud-provider)으로 구성되어 있지 않으므로 LoadBalancer 서비스 유형을 사용할 수 없습니다. 168 | 169 | 170 | `nginx` 서비스에 할당된 NodePort를 검색합니다. 171 | 172 | ```sh 173 | NODE_PORT=$(kubectl get svc nginx \ 174 | --output=jsonpath='{range .spec.ports[0]}{.nodePort}') 175 | ``` 176 | 177 | `nginx` NodePort에 해당 포트로 원격 접근을 허용하는 방화벽 규칙을 추가합니다. 178 | 179 | ``` 180 | gcloud compute firewall-rules create kubernetes-the-hard-way-allow-nginx-service \ 181 | --allow=tcp:${NODE_PORT} \ 182 | --network kubernetes-the-hard-way 183 | ``` 184 | 185 | 워커 노드 인스턴스의 외부 IP 주소 검색 186 | 187 | ``` 188 | EXTERNAL_IP=$(gcloud compute instances describe worker-0 \ 189 | --format 'value(networkInterfaces[0].accessConfigs[0].natIP)') 190 | ``` 191 | 192 | 외부 IP 주소와 `nginx` 노드 포트를 사용하여 HTTP 요청을 합니다. 193 | 194 | ``` 195 | curl -I http://${EXTERNAL_IP}:${NODE_PORT} 196 | ``` 197 | 198 | > 출력 199 | 200 | ``` 201 | HTTP/1.1 200 OK 202 | Server: nginx/1.15.4 203 | Date: Sun, 30 Sep 2018 19:25:40 GMT 204 | Content-Type: text/html 205 | Content-Length: 612 206 | Last-Modified: Tue, 25 Sep 2018 15:04:03 GMT 207 | Connection: keep-alive 208 | ETag: "5baa4e63-264" 209 | Accept-Ranges: bytes 210 | ``` 211 | 212 | ## 신뢰할 수 없는 (untrusted) 워크로드 213 | 214 | 이 섹션에서는 [gVisor](https://github.com/google/gvisor)를 사용하여 신뢰할 수 없는 워크로드를 실행할 수 있는지 확인합니다. 215 | 216 | `신뢰할 수 없는` 파드 만들기 217 | 218 | ```yaml 219 | cat < 출력 306 | 307 | ``` 308 | I0930 19:31:31.419765 21217 x:0] *************************** 309 | I0930 19:31:31.419907 21217 x:0] Args: [runsc --root /run/containerd/runsc/k8s.io ps af7470029008a4520b5db9fb5b358c65d64c9f748fae050afb6eaf014a59fea5] 310 | I0930 19:31:31.419959 21217 x:0] Git Revision: 50c283b9f56bb7200938d9e207355f05f79f0d17 311 | I0930 19:31:31.420000 21217 x:0] PID: 21217 312 | I0930 19:31:31.420041 21217 x:0] UID: 0, GID: 0 313 | I0930 19:31:31.420081 21217 x:0] Configuration: 314 | I0930 19:31:31.420115 21217 x:0] RootDir: /run/containerd/runsc/k8s.io 315 | I0930 19:31:31.420188 21217 x:0] Platform: ptrace 316 | I0930 19:31:31.420266 21217 x:0] FileAccess: exclusive, overlay: false 317 | I0930 19:31:31.420424 21217 x:0] Network: sandbox, logging: false 318 | I0930 19:31:31.420515 21217 x:0] Strace: false, max size: 1024, syscalls: [] 319 | I0930 19:31:31.420676 21217 x:0] *************************** 320 | UID PID PPID C STIME TIME CMD 321 | 0 1 0 0 19:26 10ms app 322 | I0930 19:31:31.422022 21217 x:0] Exiting with status: 0 323 | ``` 324 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /docs/lab-05.md: -------------------------------------------------------------------------------- 1 | # LAB-05. Kubernetes Control Plane 부트스트래핑 2 | 3 | - 이 랩에서는 쿠버네티스 두 개의 마스터 노드 VM 상에서 컨트롤 플레인을 부트스트랩 합니다. 4 | - 각 노드에는 Kubernetes API Server, Scheduler 및 Controller Manager가 설치됩니다. 5 | - Kubernetes API 서버를 원격 클라이언트에 노출시키는 로드 밸런서를 만듭니다. 6 | 7 | 8 | ## 0. 들어가기 전에 9 | 10 | - [컨트롤 플레인](https://kubernetes.io/ko/docs/concepts/#%ec%bf%a0%eb%b2%84%eb%84%a4%ed%8b%b0%ec%8a%a4-%ec%bb%a8%ed%8a%b8%eb%a1%a4-%ed%94%8c%eb%a0%88%ec%9d%b8) 11 | - 쿠버네티스 클러스터를 제어하는 ​​서비스 (by 컨트롤 플레인 컴포넌트) 12 | - 쿠버네티스 오브젝트의 레코드와 상태를 관리 13 | - 클러스터에 대한 글로벌한 의사결정, 이벤트에 대한 탐지 및 응답 수행 14 | - 컨트롤 플레인 컴포넌트 (마스터) 15 | - **kube-apiserver** : 쿠버네티스 API 제공. 사용자 - 클러스터 간 인터페이스 16 | - **etcd** : 쿠버네티스 클러스터 데이터 저장소 17 | - **kube-scheduler** : 가용한 워커 노드에 파드(pods) 스케줄링 18 | - **kube-controller-manager** : 다양한 기능을 제공하는 4가지 종류의 컨트롤러를 실행 19 | - ~~cloud-controller-manager : 클라우드 제공사업자와 상호작용 (AWS, GCP, Azure)~~ 20 | 21 | 22 | > 위 쿠버네티스 컴포넌트에 대한 설명은 [이곳](https://kubernetes.io/ko/docs/concepts/overview/components/)을 참고하세요. 23 | 24 | 25 | - 아키텍쳐 26 | ![architecture](kthw.png "architecture") 27 | 28 | 29 | ## 1. 준비 사항 30 | 31 | 이 랩에서 명령은 마스터 노드인 `controller-0`,`controller-1` 모두 에서 실행되어야 합니다. 32 | 33 | GCP 인스턴스 ssh 로그인 34 | ``` 35 | gcloud compute ssh controller-0 36 | ``` 37 | 38 | ## 2. 쿠버네티스 Control Plane 프로비저닝 39 | 40 | 쿠버네티스 구성 디렉토리 생성 41 | 42 | ``` 43 | sudo mkdir -p /etc/kubernetes/config 44 | ``` 45 | 46 | ### 2-1. 쿠버네티스 컨트롤러 바이너리 다운로드 및 설치 47 | 48 | 쿠버네티스 릴리스 바이너리 다운로드 (v.1.12.0) 49 | 50 | ``` 51 | wget -q --show-progress --https-only --timestamping \ 52 | "https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kube-apiserver" \ 53 | "https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kube-controller-manager" \ 54 | "https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kube-scheduler" \ 55 | "https://storage.googleapis.com/kubernetes-release/release/v1.12.0/bin/linux/amd64/kubectl" 56 | ``` 57 | 58 | 쿠버네티스 바이너리 설치 59 | 60 | ``` 61 | { 62 | chmod +x kube-apiserver kube-controller-manager kube-scheduler kubectl 63 | sudo mv kube-apiserver kube-controller-manager kube-scheduler kubectl /usr/local/bin/ 64 | } 65 | ``` 66 | 67 | ### 2-2. 쿠버네티스 API Server 구성하기 68 | 69 | ``` 70 | { 71 | sudo mkdir -p /var/lib/kubernetes/ 72 | 73 | sudo mv ca.pem ca-key.pem kubernetes-key.pem kubernetes.pem \ 74 | service-account-key.pem service-account.pem \ 75 | encryption-config.yaml /var/lib/kubernetes/ 76 | } 77 | ``` 78 | 79 | 인스턴스 내부 IP 주소는 API 서버를 클러스터 멤버에게 알리는데 사용됩니다. 인스턴스의 내부 IP 주소를 가져옵니다. 80 | 81 | ``` 82 | INTERNAL_IP=$(curl -s -H "Metadata-Flavor: Google" \ 83 | http://metadata.google.internal/computeMetadata/v1/instance/network-interfaces/0/ip) 84 | ``` 85 | 86 | 위에서 확인된 마스터 노드 0, 1의 ip를 컨트롤러IP 변수에 각각 넣어줍니다. (예) 87 | ``` 88 | CONTROLLER0_IP=10.240.0.10 89 | CONTROLLER1_IP=10.240.0.11 90 | ``` 91 | 92 | `kube-apiserver.service` systemd 파일 생성 93 | 94 | ```sh 95 | cat < 1.13 버전부터는 encryption-provider-config 로 변경 140 | 141 | > 상황에 따라 --kubelet-preferred-address-types=InternalIP,InternalDNS,Hostname,ExternalIP,ExternalDNS 추가해야할 수 있음 142 | 143 | > check : endpoint-reconciler-type=master-count 가 빠져있음 144 | 145 | ### 2-3. 쿠버네티스 Controller Manager 구성하기 146 | 147 | ``` 148 | sudo mv kube-controller-manager.kubeconfig /var/lib/kubernetes/ 149 | ``` 150 | 151 | `kube-controller-manager.service` systemd 파일 생성 152 | 153 | ```sh 154 | cat < `/healthz` API 서버 엔드포인트는 기본적으로 인증을 필요로 하지 않습니다. 258 | 259 | HTTP 상태 검사를 처리 할 기본 웹서버 설치 260 | 261 | ```sh 262 | sudo apt-get install -y nginx 263 | ``` 264 | 265 | ```sh 266 | cat > kubernetes.default.svc.cluster.local < 이 가이드는 Kubelet `--authorization-mode` 플래그를 `Webhook`으로 설정합니다. Webhook 모드는 [SubjectAccessReview](https://kubernetes.io/docs/admin/authorization/#checking-api-access) API를 사용하여 접근 허가를 결정합니다. 320 | 321 | ``` 322 | gcloud compute ssh controller-0 323 | ``` 324 | 325 | Kubelet API에 접근 권한이 있는 `system:kube-apiserver-to-kubelet` [ClusterRole](https://kubernetes.io/docs/admin/authorization/rbac/#role-and-clusterrole) 을 만듭니다. 326 | 327 | ```yaml 328 | cat < 출력 451 | 452 | ```json 453 | { 454 | "major": "1", 455 | "minor": "12", 456 | "gitVersion": "v1.12.0", 457 | "gitCommit": "0ed33881dc4355495f623c6f22e7dd0b7632b7c0", 458 | "gitTreeState": "clean", 459 | "buildDate": "2018-09-27T16:55:41Z", 460 | "goVersion": "go1.10.4", 461 | "compiler": "gc", 462 | "platform": "linux/amd64" 463 | } 464 | ``` 465 | --------------------------------------------------------------------------------