[우아한테크코스] 10월 7일 TIL
[infra] 쿠버네티스 설치하기
- kops를 사용한 aws에 쿠버네티스 설치하기
kubeadm에 비해 서버 인스턴스와 네트워크 리소스를 클라우드에서 자동으로 생성해 설치해준다.
Kops 실행 바이너리 다운로드
curl -Lo kops https://github.com/kubernetes/kops/releases/download/$(curl -s https://api.github.com/repos/kubernetes/kops/releases/latest | grep tag_name | cut -d '"' -f 4)/kops-linux-amd64
chmod +x kops
sudo mv kops /usr/local/bin/kops
kubectl 실행 바이너리 다운로드
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x kubectl
sudo mv kubectl /usr/local/bin/
iam 역할 부여 (kube-role)
sudo apt update
sudo apt install awscli
aws configure
...
Default region name [None]: ap-northeast-2
...
aws ec2 describe-instances
쿠버네티스를 설치한 ec2 인스턴스에 배포할 ssh 키 생성
ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
kops 재인증
kops export kubecfg --admin
클러스터 생성
클러스터의 설정 정보 저장
export BUCKET_NAME=zzimkkong-kube
export NAME=2021-zzimkkong.k8s.local
export KOPS_STATE_STORE=s3://$BUCKET_NAME
aws s3api create-bucket --bucket $BUCKET_NAME --create-bucket-configuration LocationConstraint=ap-northeast-2
aws s3api put-bucket-versioning --bucket $BUCKET_NAME --versioning-configuration Status=Enabled
kops create cluster --zones ap-northeast-2a --topology=public --ssh-access=172.16.0.0/16,192.168.0.0/24,192.168.1.0/24,192.168.2.0/24,192.168.3.0/24 --network-cidr=192.168.1.0/24 --networking calico --ssh-public-key ~/.ssh/id_rsa.pub $NAME
kops create cluster --zones ap-northeast-2c --topology=public --ssh-access=172.16.0.0/16,192.168.0.0/24,192.168.1.0/24,192.168.2.0/24,192.168.3.0/24 --network-cidr=192.168.1.0/24 --networking calico --ssh-public-key ~/.ssh/id_rsa.pub $NAME
특정 vpc에 만들기 -> edit으로 수정할것!!
// yaml 파일 생성
kops get clusters ${CLUSTER_NAME} -o yaml > cluster-config.yaml
// yaml 파일 수정
vi cluster-config.yaml
// yaml 교체
kops replace -f cluster.yaml
클러스터 수정 (노드 갯수, 인스턴스 타입 등)
kops get cluster
kops edit cluster $NAME
# spec.networkID: vpc-0ec31c5f77f2af273
# spec.additionalNetworkCIDRs:
- 192.168.2.0/24
- 192.168.3.0/24
# spec.subnets.cidr: 서브넷 cidr
# spec.subnets.id: 서브넷 id
kops edit ig --name=$NAME nodes-ap-northeast-2a
kops edit ig --name=$NAME master-ap-northeast-2a
kops update cluster --name $NAME --yes --admin
클러스터 생성 확인
//설치 진행상황 확인
kops validate cluster --wait 10m
kubectl cluster-info
kubectl get nodes --show-labels
kops 재인증
kops export kubecfg --admin
// 오랜만에 재접속을 해보면 세션이 끊겨 아래와 같은 에러가 발생할 수 있는데요. 그럴 때는 위의 명령어를 실행해주면 됩니다.
// error: You must be logged in to the server (Unauthorized)
클러스터 삭제
kops delete cluster $NAME --yes
Required value: Please set the –state flag or export KOPS_STATE_STORE 오류
export KOPS_STATE_STORE=s3://yujo-apple-clone
pod 생성
yaml 파일 작성
apiVersion: v1
kind: Pod
metadata:
name: my-app-pod
spec:
containers:
- name: my-app-container //이 name 여러개 주면 container 여러개 띄우기
- image: nginx:test
ports:
- containerPort: 80
protocol: TCP
생성 명령어
kubectl apply -f my-app-pod.yaml
생성된 pod들 확인
kubectl get pods
//주소 확인
kubectl get pods -o wide
//포드에 변화 생기면 콘솔 출력
kubectl get pods -w
//포드 로그 출력
kubectl logs ${POD_NAME}
세부사항 확인(ip)
kubectl describe pods my-app-pod
pod 실행
kubectl exec -it my-app-pod bash
//로그 확인
kubectl logs my-app-pod
//pod ip로 curl 명령 보내기
kubectl run -i --tty --rm debug --image=alicek106/ubuntu:curl --restart=Never curl 100.119.134.70 | grep Hello
오브젝트 삭제
kubectl delete -f my-app-pod.yaml
kubectl delete pod my-app-pod
모든 오브젝트 삭제
kubectl delete deployment,pod,rs --all
replicatset 생성
yaml 파일 작성
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: replicaset-application
spec:
//레플리카셋 정의
replicas: 3 //동일한 포드 유지할 개수
selector:
matchLabels:
app: my-app-pods-label //key: value로 정의
//포드 정의
template:
metadata:
name: my-app-pod
labels:
app: my-app-pods-label
spec:
containers:
- name: my-app-container
- image: nginx:test
ports:
- containerPort: 8080
protocol: TCP
생성할 때: pod와 같은 생성 명령어
생성 확인 명령어 (–show-labels 옵션으로 라벨까지 확인 가능, -l app으로 필터링도 가능)
kubectl get rs(replicasets)
수정할 때: (pod 개수 늘리고 싶을 때) 그냥 yaml 수정하고 apply 다시 하면 됨
삭제할 때: pod와 같은 삭제 명령어
deployment 생성
Yaml 파일 작성
apiVersion: apps/v1
kind: Deployment
metadata:
name: hostname-deployment
spec:
replicas: 3
selector:
matchLabels:
app: webserver
template:
metadata:
name: my-webserver
labels:
app: webserver
spec:
containers:
- name: my-webserver
image: alicek106/rr-test:echo-hostname
ports:
- containerPort: 80
생성할 때: pod와 같은 생성 명령어
생성 확인 명령어 (–show-labels 옵션으로 라벨까지 확인 가능, -l app으로 필터링도 가능)
kubectl get deployment(deploy)
수정할 때: (pod 개수 늘리고 싶을 때) 그냥 yaml 수정하고 apply 다시 하거나, kubectl edit deploy my-app
삭제할 때: pod와 같은 삭제 명령어
포드 개수 줄일때
kubectl scale --replicas=1 deployment ${DEPLOY_NAME}
버전 저장
kubectl apply -f deployment-nginx.yaml --record
-
replicaset 내의 pod에 변화가 생기면 이전 replicaset을 0 으로 줄이고 새로운 replicaset을 생성한다. 이는 replicaset 조회 시 deployment의 이름 뒤 해시값을 통해 알 수 있다.
-
버전 조회
//명령어 kubectl rollout history deployment ${DEPLOYMENT_NAME} //결과 deployment.apps/my-nginx-deployment REVISION CHANGE-CAUSE 1 kubectl apply --filename=deployment-nginx.yaml --record=true 2 kubectl set image deployment my-nginx-deployment nginx=nginx:1.11 --record=true
-
버전 롤백
kubectl rollout undo deployment ${DEPLOYMENT_NAME} --to-revision=${VERSION}
-
지금 돌아가고 있는 정보 조회
kubectl describe deploy ${DEPLOYMENT_NAME}
기타 deploy 관련 명령어
## 업데이트
kubectl set image deployment my-app subway=[이미지]:[새로운버전] --record
## 배포 상태 확인
kubectl rollout status deployment my-app
## 이미지 태그 확인
kubectl get deployments my-app -oyaml | grep image
## 배포 히스토리 확인
kubectl rollout history deployment my-app
## 롤백
kubectl rollout undo deployment my-app
kubectl rollout undo deployment my-app --to-revision=1
## Scale out
kubectl scale deployment my-app --replicas=5
service 생성
yaml 파일 생성
apiVersion: v1
kind: Service
metadata:
name: hostname-svc-loadbalancer
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
spec:
externalTrafficPolicy: Local //처음 받은 노드에서 포드 실행
ports:
- name: web-port
port: 8080
targetPort: 80 // 고유한 ip 할당받아 사용할 포트 지정
nodePort: 31000 // inbound 규칙 허용된 접속 가능한 포트 지정
selector:
app: webserver // 라벨 지정
type: loadbalancer // 서비스 타입 지정
생성 확인 명령어(기본 kubernetes 존재)
kubectl get service(svc)
//yaml 파일 조회
kubectl get svc ${SERVICE_NAME} -o yaml
외부에서 요청 보내기
curl a01235b4b5b0e4166af809e977b0678c-1789225630.ap-northeast-2.elb.amazonaws.com --silent | grep jellllo
Ingress 생성
Yaml 파일 생성
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-example
annotations:
nginx.ingress.kubernetes.io/rewrite-target: / # [4]
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: alicek106.example.com # [1]
http:
paths:
- path: /echo-hostname # [2]
backend:
serviceName: hostname-service # [3]
servicePort: 80
- [1] 이 도메인으로 접근하는 요청에 대한 규칙 적용,
(/|$)(.*)
는 .*를 통해 경로 전달 - [2] 이 경로에 들어온 요청을 어느 서비스에 전달할지, /echo-hostname이라는 경로의 요청을 backend에 정의된 서비스에 전달
- [3] path로 들어온 요청이 어느 서비스와 포트에 전달할지 지정
- [4] host-servicedml /로 전달,
/$2
로 하면 path 에서 획득한 경로 전달
1.9 version
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: zzimkkong-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: zzimkkong.kro.kr
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: zzimkkong-lb
port:
number: 8080
생성확인 명령어
kubectl get ingress(ing)
Nginx 인그레스 컨트롤러 설치 - helm을 이용
# helm 설치
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash -s -- --version v3.2.2
helm repo add stable https://charts.helm.sh/stable/
helm repo update
helm repo list
helm search repo stable
# nginx 설치
kubectl create ns ctrl
helm install nginx-ingress stable/nginx-ingress --version 1.40.3 -n ctrl
kubectl get pod -n ctrl
kubectl get svc -n ctrl
# aws 도메인 검색 -> DNS 사이트에 등록
kubectl get svc -nctrl nginx-ingress-controller -ojsonpath="{.status.loadBalancer.ingress[0]}"
//모든 오브젝트 조회
kubectl get ing,svc --all-namespaces
nginx-ingress-controller가 연결한 서비스에 연결해줌, 이거는 플랫폼에서 적용해주는것
그거의 external-ip로 접근하면 됨
Nginx 인그레스 컨트롤러 설치 - github 이용
https://kubernetes.github.io/ingress-nginx/deploy 참고
kubectl apply -f https://raw.githubusercontent.com/ingress-nginx/controller-v0.35.0/deploy/static/provider/aws/deploy.yaml
TLS 설정
cert-manager 설치
kubectl create ns cert-manager
## cert-manager 관련 사용자 정의 리소스 생성
kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.15.1/cert-manager.crds.yaml
## jetstack repo 추가
helm repo add jetstack https://charts.jetstack.io
## cert-manager 설치
helm install cert-manager jetstack/cert-manager --namespace cert-manager --version v0.15.1
Cert-manager yaml 파일 생성
apiVersion: cert-manager.io/v1alpha2
kind: ClusterIssuer
metadata:
name: http-issuer
spec:
# 자동으로 인증서의 생성 및 연장을 관리해주는 타입
acme:
email: [이메일주소]
# 어떤 acme 서버(인증서 발급 CA)를 사용할지 지정
server: https://acme-v02.api.letsencrypt.org/directory
# 사용자의 개인키를 저장할 Secret 리소스 이름을 지정
privateKeySecretRef:
name: issuer-key
# 도메인 주소에 대한 소유권을 증명하기 위한 방법 선택. http 요청(http01)과 DNS Lookup(dns01) 방법이 있음
solvers:
- http01:
# Ingress 컨트롤러로 NGINX를 사용
ingress:
class: nginx
cert-manager 실행
kubectl apply -f cluterissuer.yaml
kubectl get clusterissuer
인증서 ingress에 적용
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
# 앞서 생성한 발급자 지정
cert-manager.io/cluster-issuer: http-issuer
name: nginx-tls
spec:
rules:
- host: [외부에서 접근할 도메인] #이건 왠지 모르겠지만 주면 안된다!
http:
paths:
- path: /
backend:
serviceName: subway-service
servicePort: 80
tls:
- hosts:
- [외부에서 접근할 도메인]
secretName: nginx-tls
-
spec.tls.hosts.secretName
Secret 리소스를 생성하지 않아도 cert-manager에서 자동으로 인증서를 발급받아서 Secret을 생성한다. 사용자는 생성될 Secret의 이름만 지정하면 된다.
인증서 적용 확인
watch kubectl get certificate
//True 되면 완성
scp -i ~/Downloads/KEY-zzimkkong.pem ~/Downloads/backend-0.0.1-SNAPSHOT.jar ubuntu@3.38.74.217:/home/ubuntu/
리소스 고가용성 확립
- 사용량 확인
# 설치
helm install metrics-server stable/metrics-server --version 2.11.1 --namespace ctrl
# 설치 확인 (Running)
watch kubectl get pod -nctrl
# pod 사용량 확인
kubectl top pod
# node 사용량 확인
kubectl top node
-
Horizontal Pod Autoscaler 적용
cpu 사용량에 따라 replicationController, replicaSet, deploy, statefulset의 파드 개수를 자동으로 관리
메트릭이 사용자가 설정한 값과 일치하도록 컨트롤러 관리자의
--horizontal-pod-autoscaler-sync-period
플래그(기본값은 15초)에 의해 제어되는 주기를 가진 컨트롤 루프로 구현됨원하는 레플리카 수 = ceil[현재 레플리카 수 * ( 현재 메트릭 값 / 원하는 메트릭 값 )]
을 지키게 됨 -
yaml 파일 생성
apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata: name: my-app spec: maxReplicas: 100 minReplicas: 1 scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: my-app targetCPUUtilizationPercentage: 50
-
확인
kubectl get hpa
EFK 적용하기
efk는 로그를 수집해서 유의미한 지표로 만들기 위함
# 아래 파일에 로그 저장됨
/var/lib/docker/containers/<CONTAINER_ID>/<CONTAINER_ID>-json.log
설치하기
helm fetch --untar stable/elastic-stack --version 2.0.1
$ vi elastic-stack/values.yaml
// 12 line
logstash:
enabled: false # 기존 true
// 29 line
fluent-bit:
enabled: true # 기존 false
$ vi elastic-stack/charts/fluent-bit/values.yaml
// 45 line
backend:
type: es # 기존 forward
es:
host: efk-elasticsearch-client # 기존 elasticsearch
// 226 line
input:
tail:
memBufLimit: 5MB
parser: docker
path: /var/log/containers/*.log
ignore_older: ""
systemd:
enabled: true # 기존 false
filters:
systemdUnit:
- docker.service
- kubelet.service
# - node-problem-detector.service --> 주석처리
$ vi elastic-stack/charts/kibana/values.yaml
// 79 line
ingress:
enabled: true # 기존 false
hosts:
- kibana.techcourse.kro.kr # DNS 설정
annotations:
kubernetes.io/ingress.class: nginx
$ helm install efk ./elastic-stack
# NAME: efk
# LAST DEPLOYED: Sat Apr 17 20:15:13 2021
# NAMESPACE: default
# STATUS: deployed
# REVISION: 1
# NOTES:
# The elasticsearch cluster and associated extras have been installed.
# Kibana can be accessed:
# ...
# pod, svc, ingress가 정상적으로 실행되는지 확인
watch kubectl get pod,svc,ingress
-
Helm 이란?
쿠버네티스 package managing tool로 npm과 유사하다.
package format인 chart를 사용하는데 쿠버네티스 리소스를 describe 하는 파일들의 집합이다.
-
taints 문제 해결
kubectl taint nodes --all node-role.kubernetes.io/master-
https://github.com/calebhailey/homelab/issues/3
모니터링 도구 - 프로메테우스 적용
그라파나는 프로메테우스가 수집해온 정보를 시각화해줌(cpu 사용량, pod 활성화, node 메모리 사용량과 같은 하드웨어 쪽)
직접 메트릭을 수집하는 pull 방식
- exporter: 실제 메트릭을 수집하는 수집기, 프로메테우스에 전달하는 역할
- Prometheus: 메트릭을 수집하는 주체로 데이터 저장소, 쿼리엔진의 역할
- grafana: 시각화 툴
- Alert-manager: 알람 발생
템플릿 사용
-
helm 설치
helm fetch --untar stable/prometheus-operator --version 8.16.1
helm install mon ./prometheus-operator
watch kubectl --namespace default get pods -l "release=mon"
-
yaml 파일 수정
vi prometheus-operator/values.yaml
// 495 line
grafana:
ingress:
enabled: true # 기존 false
annotations:
kubernetes.io/ingress.class: nginx # 추가
cert-manager.io/cluster-issuer: http-issuer
hosts:
- grafana.zzimkkong-k8s.kro.kr # DNS 설정
tls:
- secretName: mon-grafana
hosts:
- grafana.zzimkkong-k8s.kro.kr
[infra] mysql docker에 띄우기
version: '3'
services:
zzimkkong-db:
image: library/mysql:5.7
container_name: zzimkkong-db
restart: always
ports:
- 13306:3306
environment:
MYSQL_ROOT_PASSWORD: 1234
TZ: Asia/Seoul
volumes:
- ./zzimkkong-db/conf.d:/etc/mysql/conf.d
- ./zzimkkong-db/data:/var/lib/mysql
- ./zzimkkong-db/init:/docker-entrypoint-initdb.d
platform: linux/x86_64