- Kubernetes The Hard Way2024년 01월 05일 23시 18분 37초에 업로드 된 글입니다.작성자: 재형이반응형
- 필자가 CKA를 준비하면서 쿠버네티스의 구조를 이해하는데 많은 도움을 받았던 쿠버네티스 어렵게 구성해보기! 챌린지를 포스팅해보려고 한다.
- https://github.com/kelseyhightower/kubernetes-the-hard-way
GitHub - kelseyhightower/kubernetes-the-hard-way: Bootstrap Kubernetes the hard way on Google Cloud Platform. No scripts.
Bootstrap Kubernetes the hard way on Google Cloud Platform. No scripts. - GitHub - kelseyhightower/kubernetes-the-hard-way: Bootstrap Kubernetes the hard way on Google Cloud Platform. No scripts.
github.com
- 실습을 진행하기에 앞서 필요한 컴퓨팅 리소스들은 AWS 클라우드를 이용하여 배포할 생각입니다.
- 위에 실습에서는 gcloud를 사용하고 저희는 AWS를 사용하기 때문에 여기 링크를 참조해주세요. aws cli 를 사용한 실습입니다.
- https://github.com/go4real/kubernetes-the-hard-way-aws
GitHub - go4real/kubernetes-the-hard-way-aws: AWS version of Kelsey's kubernetes-the-hard-way
AWS version of Kelsey's kubernetes-the-hard-way. Contribute to go4real/kubernetes-the-hard-way-aws development by creating an account on GitHub.
github.com
- 총 3개의 controlplane과 3개의 worker node를 배포할 것 입니다.
- 배포 시에는 IaC를 사용할 것이며 Terraform을 사용하도록 하겠습니다.
- 참고로 위 aws cli를 사용한 실습서를 참고하실 경우에는 VPC CIDR이랑 서브넷 CIDR, 그리고 controller.tf, worker.tf에 있는 ip들을 수정해주셔야 합니다.
실습 구성도 - 실습을 위해 모두 Public으로 구성...ㅎ
파일 구조 더보기########### main.tf ########### terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.31.0" } } } provider "aws" { region = "ap-northeast-2" } module "dev" { source = "../../" # project project_name = var.project_name environment = var.environment # VPC cidr_vpc = var.cidr_vpc cidr_public = var.cidr_public # EC2 instance_type = var.instance_type key_name = var.key_name volume_size = var.volume_size } ########### variables.tf ########### # project variable "project_name" { default = "kubernetes-the-hard-way" } variable "environment" { default = "kubernetes" } # VPC variable "cidr_vpc" { default = "10.240.0.0/16"} variable "cidr_public" { default = "10.240.0.0/24" } # EC2 variable "key_name" { default = "linux-practice" } variable "instance_type" { default = "t3.micro" } variable "volume_size" { default = 50 } ########### vpc.tf ########### # VPC resource "aws_vpc" "vpc" { cidr_block = "${var.cidr_vpc}" enable_dns_support = true enable_dns_hostnames = true tags = { Name = "${var.project_name}" } } # Subnet resource "aws_subnet" "public" { vpc_id = aws_vpc.vpc.id availability_zone = "ap-northeast-2a" cidr_block = "${var.cidr_public}" map_public_ip_on_launch = true tags = { Name = "${var.environment}" } } # Internet Gateway resource "aws_internet_gateway" "igw" { vpc_id = aws_vpc.vpc.id tags = { Name = "${var.environment}" } } # Security group resource "aws_default_security_group" "default" { vpc_id = aws_vpc.vpc.id tags = { Name = "${var.environment}" } } # Route table resource "aws_route_table" "public" { vpc_id = aws_vpc.vpc.id tags = { Name = "${var.environment}" } } resource "aws_route_table_association" "public" { subnet_id = aws_subnet.public.id route_table_id = aws_route_table.public.id } resource "aws_route" "public" { route_table_id = aws_route_table.public.id gateway_id = aws_internet_gateway.igw.id destination_cidr_block = "0.0.0.0/0" } ########### controllers.tf ########### # Controller Instance resource "aws_instance" "controllers" { # count = length(data.aws_network_interfaces.controllers.ids) for_each = toset([ "0", "1", "2" ]) associate_public_ip_address = true vpc_security_group_ids = [aws_security_group.sg.id] subnet_id = aws_subnet.public.id source_dest_check = false ami = data.aws_ami.ubuntu.id key_name = "${var.key_name}" instance_type = "${var.instance_type}" private_ip = "10.240.0.1${each.key}" user_data = <<-EOF name=controller-${each.key} EOF ebs_block_device { volume_size = "${var.volume_size}" delete_on_termination = true device_name = "/dev/sda1" tags = { Name = "${var.environment}" } } tags = { Name = "controller-${each.key}" Type = "controller" } } ########### workers.tf ########### # Controller Instance resource "aws_instance" "workers" { for_each = toset([ "0", "1", "2" ]) associate_public_ip_address = true subnet_id = aws_subnet.public.id source_dest_check = false vpc_security_group_ids = [aws_security_group.sg.id] ami = data.aws_ami.ubuntu.id key_name = "${var.key_name}" instance_type = "${var.instance_type}" private_ip = "10.240.0.2${each.key}" user_data = <<-EOF name=worker-${each.key}|pod-cidr=10.200.${each.key}.0/24 EOF ebs_block_device { volume_size = "${var.volume_size}" delete_on_termination = true device_name = "/dev/sda1" tags = { Name = "${var.environment}" } } tags = { Name = "worker-${each.key}" } } ########### nlb.tf ########### # Network Load Balancer resource "aws_lb" "nlb" { name = "${var.environment}" internal = false load_balancer_type = "network" subnets = [aws_subnet.public.id] enable_deletion_protection = false tags = { Name = "${var.environment}" } } # Target Group resource "aws_lb_target_group" "tg" { name = "${var.environment}" port = 6443 protocol = "TCP" vpc_id = aws_vpc.vpc.id target_type = "ip" } resource "aws_lb_target_group_attachment" "tg" { for_each = toset([ "0", "1", "2" ]) target_group_arn = aws_lb_target_group.tg.arn target_id = data.aws_instances.controllers.private_ips[each.key] depends_on = [data.aws_instances.controllers] } output "controllers-private_ips" { value = data.aws_instances.controllers.private_ips } # Listener resource "aws_lb_listener" "listener" { load_balancer_arn = aws_lb.nlb.arn port = "443" protocol = "TCP" default_action { type = "forward" target_group_arn = aws_lb_target_group.tg.arn } } ########### security_groups.tf ########### # Security Group resource "aws_security_group" "sg"{ name = "${var.environment}" description = "Kubernetes security group" vpc_id = aws_vpc.vpc.id ingress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["10.240.0.0/16"] } ingress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["10.200.0.0/16"] } ingress { from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } ingress { from_port = 6443 to_port = 6443 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } ingress { from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } ingress { from_port = -1 to_port = -1 protocol = "icmp" cidr_blocks = ["0.0.0.0/0"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = { Name = "${var.environment}" } } ########### data.tf ########### # Data Source # Ubuntu Image ID data "aws_ami" "ubuntu" { most_recent = true filter { name = "root-device-type" values = ["ebs"] } filter { name = "architecture" values = ["x86_64"] } filter { name = "name" values = ["ubuntu/images/hvm-ssd/ubuntu-focal-20.04-amd64-server-*"] } owners = ["099720109477"] } # Controller EC2s data "aws_instances" "controllers" { instance_tags = { Type = "controller" } depends_on = [aws_instance.controllers] }
- 테라폼 경험이 많이 없어서 깔끔하진 못 합니다 ㅜㅜ
조언해주시면 감사하겠습니다!!! - Bastion Host 코드를 추가하시거나 따로 생성해서 이용해주시면 되겠습니다. (깜빡함ㅎ)
tmux 기본 명령어
- 기본 패키지 관리툴을 사용해서 설치해주면 된다.
- 기본 명령어
# 세션 리스트 확인 : tmux ls # 세션 생성 : tmux new -s example # 세션 접속 : tmux attach -t example # 창 분할하기 : ctrl+B 누르고 shift+" # 분할된 창 이동하기 : ctrl+B 누르고 화살표로 이동 # 분할된 창 크기 조절 : ctrl+B 누른 상태에서 화살표로 조절 # 세션 잠깐 나가기 : ctrl+B 누르고 D # 분할된 창들 싱크 맞추기 (키보드 입력이 동시에 됨) : ### ctrl+B 누르고 shift+: 그러면 입력창이 나옴 ### 거기에 set synchronize-pane on 입력 ### 싱크 풀려면 set synchronize-pane off 입력 ### 입력창에서 화살표 위쪽을 누르면 이전 명령어 볼 수 있다
학습 목표
- 사실 실습은 위에 깃주소에서 그대로 따라하면 되기 때문에 어렵진 않지만, 왜 이런 과정들을 거쳐야 하는지에 대해서 정리를 해볼 것이다.
- 실습 위주가 아닌 이론 위주로!!!
- 실습은 위에 테라폼 코드로 aws에 배포하고 한번 따라해보시길 바랍니다.
주의사항
https://jink1982.tistory.com/123
[Unix/Linux] vi, vim ^M 제거
vi, vim ^M 제거윈도우에서 작성한 파일을 Unix/Linux상에 올리면 개행 문자가 깨져서 ^M가 보이는 경우를 봤을 것이다. 이것은 윈도우에서는 CRLF 가 개행인데 Linux/Unix에서는 LF가 개행이라 나타나는
jink1982.tistory.com
- 윈도우에서 실습을 진행할 경우 vim 코드 작성할 때 ^M 때문에 오류가 발생하는 경우가 있더라구요. 혹시 모르니 한번 확인해보세요!!!
04-certificate-authority
https://github.com/go4real/kubernetes-the-hard-way-aws/blob/master/docs/04-certificate-authority.md
쿠버네티스의 기본적인 아키텍쳐 - 쿠버네티스는 기본적으로 PKI (Public Key Infrastructure)를 통해 API Server와 통신을 하게 된다.
- cfssl 툴을 통해 ca 인증서를 만들어서 etcd, kube-apiserver, kube-controller-manager, kube-scheduler, kubelet 및 kube-proxy와 같은 구성 요소들이 서로 tls 인증을 할 수 있게 구성해야 한다.
- CA : 믿을 수 있는 인증 기관
Admin : 쿠버네티스에 접속할 때 사용되는 어드민 계정
Kubelet : 워커노드에서 실제로 컨테이너들을 배치하고 관리하는 역할을 함
Controller Manager : 다양한 컨트롤러들을 관리함, 주요 컨트롤러 : ReplicaSet, Deployment, StatefulSet
Kube Proxy : 새로운 서비스들이 생성되거나 Pod가 추가될 때, 동작하고 있는 워커노드의 iptables에 룰을 추가함
Scheduler : 클러스터 내에서 애플리케이션 파드를 적절한 노드에 스케줄링하는 역할을 함
API Server : 각 컴포넌트 클라이언트들이 서로 통신할 때 중간에서 인증 절차를 확인하고 이어주는 역할을 함
Service Account for token : 서비스 어카운트 토큰을 생성할 때 사용한다고 함
etcd : 키•밸류 형태의 데이터를 저장하는 스토리지, 어떤 Pod가 어느 Node에 저장되어 있는지 각 Pod들 구성 등 저장
📢 etcd는 가용성을 위해 다중 클러스터 구성 시 홀수개로 구성해야 함, 왜냐하면 데이터의 일관성을 위해 RAFT 합의 알고리즘을 사용하기 때문 (과반수로 primary 클러스터를 정하는데 짝수이면 과반수가 아닐 경우가 생김)
05-kubernetes-configuration-files
- Kubernetes 클라이언트가 Kubernetes API 서버를 찾고 인증할 수 있도록 하는 kubeconfig 구성 파일을 생성한다.
- kubeconfig 파일 : kubectl 명령어가 api-server에 접근할 때 사용할 인증 정보를 가지고 있다.
- 기본적으로 kubeconfig 파일은 $HOME/.kube/config에 저장이 됩니다.
- kubeconfig 구조
apiVersion: v1 kind: Config preferences: {} clusters: - name: cluster.local cluster: certificate-authority-data: LS0tLS1... server: https://127.0.0.1:6443 - name: mycluster cluster: server: https://1.2.3.4:6443 users: - name: myadmin - name: kubernetes-admin user: client-certificate-data: LS0tLS1... client-key-data: LS0tLS1... contexts: - context: cluster: mycluster user: myadmin name: myadmin@mycluster - context: cluster: cluster.local user: kubernetes-admin name: kubernetes-admin@cluster.local current-context: kubernetes-admin@cluster.local
- clusters : 접속할 서버 정보와 관련된 것이며 서버는 여러개 있을 수 있다. 원한다면 쿠버네티스 클러스터를 여러개 설정할 수 있다.
cluster.local : 설정하지 않아도 기본적으로 구성되는 클러스터 이름
client-authority-data : kubectl이 어떤 서버에 요청할 것인지에 대한 정보와 CA 인증서를 base64로 인코딩한 것
server : 실제 api-server의 주소 - users : 인증받을 사용자
name : 사용자의 계정명
client-certificate-data, client-key-data : 사용자가 사용할 클라이언트의 인증서(공개키)와 개인키 - context : users와 clusters의 조합. 어떤 컨텍스트를 선택하느냐에 따라 클러스터와 사용자가 결정된다.
- current-context : 현재 인증에 사용하기 위한 현재 컨텍스트를 의미한다.
06-data-encryption-keys
- Secrets는 다른 쿠버네티스 리소스와 마찬가지로, 평소엔 etcd에 저장되어 있다가 API 서버와 kubelet을 거쳐 컨테이너로 전달된다.
- 보통은 권한을 가진 Client 또는 Component가 API 서버에 요청하여 Secret을 가져오지만 etcd에 직접 접근해서 Secret 값을 조회할 수 있다.
ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key /etc/kubernetes/pki/apiserver-etcd-client.key --cacert /etc/kubernetes/pki/etcd/ca.crt get /registry/secrets/default/secret1 | hexdump -C 00000000 2f 72 65 67 69 73 74 72 79 2f 73 65 63 72 65 74 |/registry/secret| 00000010 73 2f 64 65 66 61 75 6c 74 2f 73 65 63 72 65 74 |s/default/secret| 00000020 31 0a 6b 38 73 00 0a 0c 0a 02 76 31 12 06 53 65 |1.k8s.....v1..Se| 00000030 63 72 65 74 12 cd 01 0a b1 01 0a 07 73 65 63 72 |cret........secr| 00000040 65 74 31 12 00 1a 07 64 65 66 61 75 6c 74 22 00 |et1....default".| 00000050 2a 24 39 38 30 30 34 65 38 61 2d 62 64 31 37 2d |*$98004e8a-bd17-| 00000060 34 62 62 65 2d 39 32 37 35 2d 39 62 32 63 66 32 |4bbe-9275-9b2cf2| 00000070 33 62 35 66 32 62 32 00 38 00 42 08 08 fd a1 9a |3b5f2b2.8.B.....| 00000080 8f 06 10 00 7a 00 8a 01 62 0a 0e 6b 75 62 65 63 |....z...b..kubec| 00000090 74 6c 2d 63 72 65 61 74 65 12 06 55 70 64 61 74 |tl-create..Updat| 000000a0 65 1a 02 76 31 22 08 08 fd a1 9a 8f 06 10 00 32 |e..v1".........2| 000000b0 08 46 69 65 6c 64 73 56 31 3a 2e 0a 2c 7b 22 66 |.FieldsV1:..,{"f| 000000c0 3a 64 61 74 61 22 3a 7b 22 2e 22 3a 7b 7d 2c 22 |:data":{".":{},"| 000000d0 66 3a 6d 79 6b 65 79 22 3a 7b 7d 7d 2c 22 66 3a |f:mykey":{}},"f:| 000000e0 74 79 70 65 22 3a 7b 7d 7d 42 00 12 0f 0a 05 6d |type":{}}B.....m| 000000f0 79 6b 65 79 12 06 6d 79 64 61 74 61 1a 06 4f 70 |ykey..mydata..Op| 00000100 61 71 75 65 1a 00 22 00 0a |aque.."..| 00000109
- 'mykey'의 값이 'mydata' 인 것을 확인할 수 있습니다.
- 이처럼 보안상의 이유로 etcd는 암호화하는 것이 좋습니다.
ENCRYPTION_KEY=$(head -c 32 /dev/urandom | base64) cat > encryption-config.yaml <<EOF kind: EncryptionConfig apiVersion: v1 resources: - resources: - secrets providers: - aescbc: keys: - name: key1 secret: ${ENCRYPTION_KEY} - identity: {} EOF
- 해당 파일 경로를 kube-apiserver 옵션에 추가하면 됩니다.
kube-apiserver --encryption-provider-config=/파일경로/encryption-config.yaml
00000000 2f 72 65 67 69 73 74 72 79 2f 73 65 63 72 65 74 |/registry/secret| 00000010 73 2f 64 65 66 61 75 6c 74 2f 73 65 63 72 65 74 |s/default/secret| 00000020 31 0a 6b 38 73 3a 65 6e 63 3a 73 65 63 72 65 74 |1.k8s:enc:secret| 00000030 62 6f 78 3a 76 31 3a 6b 65 79 31 3a 99 7b 00 83 |box:v1:key1:.{..| 00000040 6a 16 af 2c 04 20 1f d9 db 72 57 f9 be 21 d1 49 |j..,. ...rW..!.I| 00000050 3a e7 77 f7 8f af b5 c2 ed ad f2 16 fc 47 3e 7b |:.w..........G>{| 00000060 e0 84 3d 36 2b be 65 69 8e dd 0b 9d 96 a7 85 20 |..=6+.ei....... | 00000070 b2 cb 6a a5 ee 19 7d 4e bc 34 df 91 7f c6 39 32 |..j...}N.4....92| 00000080 33 9c 17 06 dd 37 ed d0 02 7b 52 aa 50 60 c4 1f |3....7...{R.P`..| 00000090 9f a0 4f a7 c8 cd f7 38 a2 f3 57 32 14 29 8e 25 |..O....8..W2.).%| 000000a0 c9 7f e9 83 57 26 fa 30 b9 57 fa f0 13 a2 c3 15 |....W&.0.W......| 000000b0 a5 66 98 a4 53 b3 16 de b0 85 bb ad 92 50 40 50 |.f..S........P@P| 000000c0 6f a9 7d 8a c9 4a 9b 0e c1 f7 47 5d 65 a7 03 09 |o.}..J....G]e...| 000000d0 81 c2 63 4d ad 95 62 51 b0 62 8b 45 c4 c7 5a 7c |..cM..bQ.b.E..Z|| 000000e0 45 bb 68 6d e8 3d 5b 59 28 f8 2d 37 e2 bd cb da |E.hm.=[Y(.-7....| 000000f0 b9 32 f4 37 35 3e 68 86 ef 33 d6 17 3a 4c af f8 |.2.75>h..3..:L..| 00000100 de 6d 61 2e 67 7e 43 33 4d 15 ab a1 05 4d c1 af |.ma.g~C3M....M..| 00000110 76 00 78 20 1a f7 fb ea 23 70 df be 89 14 75 d9 |v.x ....#p....u.| 00000120 76 88 03 60 38 16 3e 75 fe 6b b9 0f 75 d0 36 f1 |v..`8.>u.k..u.6.| 00000130 57 e2 52 be a3 80 be 0e 5b 64 57 dc 78 8d ac 6f |W.R.....[dW.x..o| 00000140 74 e2 fd 6c 33 9a e6 30 34 47 0a |t..l3..04G.| 0000014b
- 암호화가 잘된 것을 확인할 수 있습니다.
07-bootstrapping-etcd
[Unit] Description=etcd Documentation=https://github.com/coreos [Service] Type=notify ExecStart=/usr/local/bin/etcd \\ --name ${ETCD_NAME} \\ --cert-file=/etc/etcd/kubernetes.pem \\ --key-file=/etc/etcd/kubernetes-key.pem \\ --peer-cert-file=/etc/etcd/kubernetes.pem \\ --peer-key-file=/etc/etcd/kubernetes-key.pem \\ --trusted-ca-file=/etc/etcd/ca.pem \\ --peer-trusted-ca-file=/etc/etcd/ca.pem \\ --peer-client-cert-auth \\ --client-cert-auth \\ --initial-advertise-peer-urls https://${INTERNAL_IP}:2380 \\ --listen-peer-urls https://${INTERNAL_IP}:2380 \\ --listen-client-urls https://${INTERNAL_IP}:2379,https://127.0.0.1:2379 \\ --advertise-client-urls https://${INTERNAL_IP}:2379 \\ --initial-cluster-token etcd-cluster-0 \\ --initial-cluster controller-0=https://10.0.1.10:2380,controller-1=https://10.0.1.11:2380,controller-2=https://10.0.1.12:2380 \\ --initial-cluster-state new \\ --data-dir=/var/lib/etcd Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target
- 다른 옵션들은 서버 url과 인증서 파일, 키 파일 위치들을 넣어주는 옵션이고
--data-dir은 데이터가 저장되는 파일 경로이다. - 그래서 etcd를 백업하고 restore할 때 이 부분을 새로 restore할 데이터 파일의 경로로 수정해주어야 한다.
# 현재 상태를 백업 후 <backup-file-location> 경로에 데이터 저장 ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \ --cacert=<trusted-ca-file> --cert=<cert-file> --key=<key-file> \ snapshot save <backup-file-location> # 백업된 데이터 <backup-file-location>를 <data-dir-location>에 복구 ETCDCTL_API=3 etcdctl --data-dir <data-dir-location> snapshot restore <backup-file-location>
- 이렇게 복구한 후에 etcd 옵션에서 data-dir 부분을
--data-dir=<data-dir-location> 으로 수정해주어야 함
08-bootstrapping-kubernetes-controllers
- 각 컨트롤플레인 노드에는 Kubernetes API 서버, 스케줄러, 컨트롤러 매니저와 같은 구성 요소가 설치됩니다.
- 이 실습에서는 가용성을 위해 다중 클러스터 환경으로 구성을 하였고 로드 밸런싱을 위해 단일 인터페이스로 NLB를 생성해서 사용하고 있습니다. ALB가 아니라 NLB를 사용하는 이유는 header check를 할 필요가 없기 때문에 NLB를 사용하여 더 빠른 속도에 중점을 두었습니다.
- 여기서는 binary 파일로 각 컴포넌트들을 서비스로 올려서 사용하고 있지만 static-pod를 이용하는 방법도 있습니다.
기본 static-pod 경로 : /etc/kubernetes/manifests/ - RBAC을 설정하는 부분은 지금까지 인증 절차를 거쳤으니 인가 절차를 통해 어떤 리소스에 어떤 권한을 가지고 접근할 수 있는지 부여하는 부분이다.
09-bootstrapping-kubernetes-workers
- 각 워커노드에는 runc, container networking plugins (CNI, Weave, Flannel, Calico 등), containerd, kubelet 및 kube-proxy와 같은 구성 요소가 설치됩니다.
- kubernetes v1.18 이상은 socat과 conntrack 패키지가 필수이고 ipset 패키지는 설치를 권장하며, v1.18 미만은 모두 설치를 권장한다고 합니다.
socat : socat은 의존성이 없는 두 채널 사이에서 양방향으로 데이터 전송을 중계
conntrack : netfilter (리눅스 커널 기능 중 하나)가 네트워크에서 발생하는 커넥션에 대해 해당 내용들을 기록하고 추적하기 위한 모듈이다. 즉, iptables가 netfilter를 사용하기 때문에 iptables의 상태추적 모듈이라고 볼 수 있다. iptables가 수정하는 NAT 테이블과 같은 상태들을 추적함.
ipset : 특정 ip를 차단하는데 사용하는 유틸리티인 것 같음...ㅎ (검색해도 사용법만 나오고 개념은 잘 안나오네요)
sudo apt-get update sudo apt-get -y install socat conntrack ipset
- swap : 메모리가 부족할 시 하드 디스크의 일부 공간을 활용하여 계속 작업을 할 수 있게 해줍니다. 당연히 RAM 보다 속도가 느림.
기본적으로 swap이 활성화되면 kubelet이 시작되지 않는다. 쿠버네티스가 적절한 리소스 할당과 서비스 품질을 제공할 수 있도록 스왑을 비활성화하는 것이 좋다.
# swap 상태 확인 sudo swapon --show # swap 기능 off sudo swapoff -a
10-configuring-kubectl
- 관리자 사용자 자격 증명을 기반으로 kubectl 명령줄 유틸리티를 위한 kubeconfig 파일을 생성한다.
# kubectl config 명령어로 kubeconfig 파일 생성 kubectl config set-cluster kubernetes-the-hard-way \ --certificate-authority=ca.pem \ --embed-certs=true \ --server=https://${KUBERNETES_PUBLIC_ADDRESS}:443 kubectl config set-credentials admin \ --client-certificate=admin.pem \ --client-key=admin-key.pem kubectl config set-context kubernetes-the-hard-way \ --cluster=kubernetes-the-hard-way \ --user=admin kubectl config use-context kubernetes-the-hard-way # 확인 kubectl get nodes NAME STATUS ROLES AGE VERSION ip-10-0-1-20 Ready <none> 3m35s v1.21.0 ip-10-0-1-21 Ready <none> 3m35s v1.21.0 ip-10-0-1-22 Ready <none> 3m35s v1.21.0
11-pod-network-routes
[번역] 쿠버네티스 네트워킹 이해하기#1: Pods
해당 포스트는 제가 CKA 자격증 취득을 위해 쿠버네티스 network에 대해 공부할 때 굉장히 도움이 되었던 글로써, 많은 분들이 쿠버네티스를 공부하는데에 도움이 되길 바라는 마음에서 번역해 보
coffeewhale.com
- 아주 잘 정리가 되어 있습니다. 좋은 글 감사합니다 커피 고래님
12-dns-addon
- CoreDNS를 deployment로 배포
kubectl config use-context kubernetes-the-hard-way kubectl apply -f https://storage.googleapis.com/kubernetes-the-hard-way/coredns-1.8.yaml serviceaccount/coredns created clusterrole.rbac.authorization.k8s.io/system:coredns created clusterrolebinding.rbac.authorization.k8s.io/system:coredns created configmap/coredns created deployment.apps/coredns created service/kube-dns created
- 쿠버네티스 클러스터 내 Pod에서 어떤 도메인을 찾고자 할 때 CoreDNS를 통해 질의를 하게 된다. 쿠버네티스 v1.12 부터 표준으로 채택되었다.
- CoreDNS의 여러가지 기능은 Corefile설정 파일에 원하는 것들만 플러그인처럼 추가할 수 있다. 이 Corefile 파일은 ConfigMap 오브젝트에 저장되어 있다.
kubectl -n kube-system describe configmap coredns Name: coredns Namespace: kube-system Labels: <none> Annotations: <none> Data ==== Corefile: ---- .:53 { errors health { lameduck 5s } ready kubernetes cluster.local in-addr.arpa ip6.arpa { pods insecure fallthrough in-addr.arpa ip6.arpa ttl 30 } prometheus :9153 forward . /etc/resolv.conf cache 30 loop reload loadbalance }
- Pod를 하나 만들어서 /etc/resolv.conf 파일을 확인해보면
nameserver x.x.x.x search default.svc.cluster.local svc.cluster.local cluster.local options ndots:5
- 여기서 options ndots:5는 도메인에 포함된 점(.)의 개수가 5개부터 FQDN으로 취급을 의미한다.
- 만약 어떤 Pod에서 k8s.example.coredns.ndot.options.test 같은 도메인을 찾으려고 한다면, 이 도메인은 FQDN이기 때문에 클라이언트는 k8s.example.coredns.ndot.options.test.형태로 DNS 서버에 질의를 하게 된다.
- 그리고 search 옵션은 클라이언트가 DNS 서버로부터 결과가 없다는 응답을 받으면, search 도메인 목록을 차례대로 붙여가며 추가로 DNS 서버를 호출한다.
- 위 상황에서는 최대 4번까지 서버를 호출할 수 있다.
- 이 원리를 이용해서 정확하게 FQDN을 조회할 수 있다면 DNS 조회 횟수를 줄일 수 있다.
예를 들어 coredns.test.example 같은 도메인을 찾는다고 한다면, 도메인 끝에 점(.)을 붙이지 않았더라도 요청하는 클라이언트가 자동으로 점(.)을 붙인 뒤 coredns.test.example.형태로 요청을 할 것 이다.
하지만 실제로 저 도메인이 존재하지 않기 때문에 search 목록에 해당하는 default.svc.cluster.local, svc.cluster.local, cluster.local을 모두 붙여가며 추가로 DNS를 질의하게 된다.
따라서 만약 조금이라도 CoreDNS 서버에 부하를 줄이고 싶다면, 외부 도메인을 호출할 때 마지막 점(.)을 추가하면 딱 1번만 DNS 서버에 질의할 수 있게 된다.
마무리
- 이전에 정보처리기사를 공부하면서 느꼈던 건데 공부를 할 때, 처음부터 완벽하게 하려고 하지 말고 일단 익숙해지는 것이 중요한 것 같다. 처음에는 용어들도 머릿속에 안들어오고 혼란스럽지만 꾸준히 반복해서 보다보면 점점 익숙해지고 보이지 않았던 것들이 보이게 되는 것 같다. 물론 어떻게 보면 일차원적이고 무식한 방법이라 시간이 오래 걸릴 수는 있겠지만 시험만을 위한 단기 기억 방식의 공부보다는 머릿속에 더 오래 남지 않을까...?
- 공부할 건 많고 해보고 싶은 것들도 늘어나고 있지만 조금씩이라도 꾸준하게!!! 해야겠다.
반응형'데브옵스 > 쿠버네티스&도커' 카테고리의 다른 글
k8s 프로비저닝 툴 feat.kubeadm, kubespray, kOps, Cluster API (0) 2024.09.09 delete resource 시 terminating에서 stuck 상태 해결 방법 (0) 2024.09.09 AWS EC2 쿠버네티스 환경 구축하기 (0) 2024.09.05 컨테이너의 보안을 높이는 방법 (0) 2024.03.23 컨테이너의 역사와 기술 (0) 2023.12.29 다음글이 없습니다.이전글이 없습니다.댓글