Kubernetes cluster 를 구성하고 CI/CD를 구성하여 테스트
1. CI/CD 구성을 위한 Kubernetes 구성
위 테스트 환경
OS : rhel8.x
Container : cri-o
CNI : calico
STORAGE : ceph
hosts 파일에 도메인을 지정하여 테스트(dns X)
metal lb 통해서 ip할당받은 nginx ingress로 도메인 설정
처음 마스터1 워커2로 진행하다가 워커1대를 더 추가하였다.
로직
개발자는 k8s 내 gitlab에 소스를 메인 브랜치로 퍼밋(트리거)하면 gitlab runner 가 동작하고 kaniko 를 생성하고 kaniko는 repo에 있는 dockerfile을 통하여 이미지를 생성하고 harbor에 이미지를 저장한다. 이때 harbor는 image scan 을 한다.
kaniko 는 생성된 이미지의 태그를 alpine-git 을 생성하여 manifest repo에 태그를 수정해주고 manifest repo 가 수정됨에 따라 argo cd에서 chart를 인지하여 변경된 태그의 이미지를 harbor에서 불러와 배포하게 된다.
테스트는 간단한 node js로 진행했다.
kub 설치
cat << /etc/hosts
6 [master의 IP] k8s-master-1
7 [node1의 IP] k8s-worker-1
8 [node2의 IP] k8s-worker-2
systemctl stop firewalld
systemctl disable firewalld
hostnamectl set-hostname k8s-master-1
vi /etc/selinux/config
sudo swapoff -a
vi /etc/fstab #swap 주석
sudo dnf install -y iproute-tc
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# sysctl params required by setup, params persist across reboots
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# Apply sysctl params without reboot
sudo sysctl --system
subscription-manager register #인증
louie0 / T
yum update -y
## cri-o 설치
export VERSION=1.26
sudo curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable.repo https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/CentOS_8/devel:kubic:libcontainers:stable.repo
sudo curl -L -o /etc/yum.repos.d/devel:kubic:libcontainers:stable:cri-o:$VERSION.repo https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable:cri-o:$VERSION/CentOS_8/devel:kubic:libcontainers:stable:cri-o:$VERSION.repo
sudo dnf install cri-o -y
sudo systemctl enable crio
sudo systemctl start crio
## kubelet, kubeadm, kubectl 설치
sudo vi /etc/yum.repos.d/kubernetes.repo
---
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
---
sudo dnf install -y kubelet-1.26.1 kubeadm-1.26.1 kubectl-1.26.1 --disableexcludes=kubernetes
sudo systemctl enable kubelet
sudo systemctl start kubelet
systemctl status kubelet
yum install podman -y
## worker 노드는 조인 (worker node는 여기까지하면 됨)
kubeadm join 10.11.5.160:6443 --token flrb01.mtd7t9p9p6crpoe0 --discovery-token-ca-cert-hash sha256:265f34008c63212ba046fc52346428a8979719b5a5ad0012da0059aeb0d123b5
kubectl get nodes -o wide
##master 노드 토큰생성 (24시간 뒤 초기화)
kubeadm token create
kubeadm token list
##master 노드 해쉬값 조회
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
kubeadm join 10.11.5.160:6443 --token 56cpd3.0a94cmcxjhdvm5ma --discovery-token-ca-cert-hash sha256:265f34008c63212ba046fc52346428a8979719b5a5ad0012da0059aeb0d123b5
### 로그 "Failed to get system container stats" err="failed to get cgroup stats for 오류
mkdir -p /etc/systemd/system/kubelet.service.d
vi /etc/systemd/system/kubelet.service.d/11-cgroups.conf
----
Environment="KUBELET_CGROUP_ARGS=--cgroup-driver=cgroupfs --runtime-cgroups=/systemd/system.slice --kubelet-cgroups=/systemd/system.slice"
[Service]
CPUAccounting=true
MemoryAccounting=true
----
systemctl daemon-reload
systemctl restart kubelet
kubectl top nodes
## worker node 에서 kubectl get nodes 조회시 couldn't get current server API group list 오류 해결
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/kubelet.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
## 쿠버네티스 컨피그 파일이 $home/.kube 디렉토리 아래 없어서 현재 유저정보가 컨피그파일에 반영이 안됨
## 아래는 master 노드로 설정
## calico & csi 드라이버설치
curl -L https://github.com/projectcalico/calico/releases/download/v3.24.5/calicoctl-linux-amd64 -o calicoctl
chmod 700 calicoctl
sudo mv calicoctl /usr/bin/
calicoctl node status
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.1/manifests/csi-driver.yaml
kubectl get pods -n calico-system
##istio 설치
curl -sL https://istio.io/downloadIstioctl | sh -
sudo cp ~/.istioctl/bin/istioctl /usr/local/bin
./istioctl install --set profile=demo --set components.cni.enabled=true -y
kubectl apply -n istio-system -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: kiali-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 8080
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: kiali
spec:
hosts:
- "*"
gateways:
- kiali-gateway
http:
- match:
- uri:
prefix: /kiali
route:
- destination:
port:
number: 20001
host: kiali
EOF
##Metallb 설치
kubectl get configmap kube-proxy -n kube-system -o yaml | grep strictARP
kubectl get configmap kube-proxy -n kube-system -o yaml | sed -e "s/strictARP: false/strictARP: true/" | kubectl apply -f - -n kube-system
kubectl get configmap kube-proxy -n kube-system -o yaml | grep strictARP
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.13.7/config/manifests/metallb-native.yaml
kubectl get -n metallb-system pods
vi l2-network.yaml
----------------------------------------------------------------------------------------
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: first-pool
namespace: metallb-system
spec:
addresses:
- 10.11.5.170-10.11.5.185
---
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: second-pool
namespace: metallb-system
spec:
addresses:
- 10.11.5.190-10.11.5.200
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: l2-network
namespace: metallb-system
spec:
ipAddressPools:
- first-pool
- second-pool
------------------------------------------------------------------------------------------------------------------------------------
kubectl apply -n metallb-system -f l2-network.yaml
##Ceph 설치 (https://www.itmaya.co.kr/wboard/view.php?wb=tech&idx=35)
##Ceph 강제삭제 (https://rook.io/docs/rook/v1.11/Getting-Started/ceph-teardown/#removing-the-cluster-crd-finalizer)
for CRD in $(kubectl get crd -n rook-ceph | awk '/ceph.rook.io/ {print $1}'); do
kubectl get -n rook-ceph "$CRD" -o name | \
xargs -I {} kubectl patch -n rook-ceph {} --type merge -p '{"metadata":{"finalizers": []}}'
done
## Ceph 트러블슈팅
ceph dashboard 나 ceph health에서
HEALTH_WARN application not enabled on 1 pool(s)가 발생할 경우
ceph-mon에서
sudo ceph health
sudo ceph health detail
여기서 문제가 되는 pool을 확인한다
만약 풀이 images 라면
sudo ceph osd pool application enable images rgw
sudo ceph health
정상인거 확인
##gitlab 설치
helm repo add gitlab https://charts.gitlab.io/
helm repo update
helm search repo git
helm install gitlab gitlab/gitlab -f values.yaml -n gitlab-ee --set certmanager-issuer.email=xxx@xxx.com
helm delete gitlab -n gitlab-ee
##gitlab root password 확인
kubectl get secret -n gitlab-ee gitlab-gitlab-initial-root-password -o jsonpath="{.data.password}" | base64 -d ; echo
환경이 도메인을 dns에 등록하지않아 gitlab runner 설치가 좀 애먹었는데 config를 깜빡하고 적지않은거같은데
기억을 더듬자면 ssl 인증서 부분때문에 gitlab 과 연동부분이 오류가 났었다.
해결법은 아마도 .. 기억은 잘 안나지만 ssl false 거나 인증서를 runner에게 줬거나 심었거나 했던거같다..
## kubernetes metric server 설치 (kubectl top)
https://velog.io/@_zero_/%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-metrics-server-%EC%84%A4%EC%B9%98
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
metrics-server 디플로이먼트 설정 수정
--metric-resolution=15s 밑에
"--kubelet-insecure-tls" 설정 추가
dnsPolicy: ClusterFirst 밑에
"hostNetwork: true" 설정 추가
kubectl top node
kubectl top pod
manifest repo 는 halm chart로 생성
tagging 을 해주는 스크립트
# tagging.sh
sed -i "s|tag: .*|tag: $CI_COMMIT_SHORT_SHA|" /helm-repo/helm-chart/values.yaml
values.yaml
----------------------------------
# Default values for test-chart.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
replicaCount: 1
image:
repository: harbor.xxx.com/gitlab-instance-acb80999/test
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: 494e26b7
# tag: 494e26b7
imagePullSecrets:
- name: harbor-crt
nameOverride: ""
fullnameOverride: ""
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
podAnnotations: {}
podSecurityContext: {}
# fsGroup: 2000
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
service:
type: ClusterIP
port: 3000
ingress:
enabled: true
className: "nginx"
annotations:
#kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
hosts:
- host: cicdtest.xxx.com
paths:
- path: /
pathType: ImplementationSpecific
tls:
- secretName: xxx.com-ssl
hosts:
- cicdtest.xxx.com
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 100
targetCPUUtilizationPercentage: 80
# targetMemoryUtilizationPercentage: 80
nodeSelector: {}
tolerations: []
affinity: {}
----------------------------------
.gitlab-ci.yml
stages:
- build
build:
stage: build
image:
# 구글 공식 kaniko 이미지 repository 사용
# debug 태그 이미지를 사용해야 파이프라인 출력 내용 확인 가능
name: gcr.io/kaniko-project/executor:debug
# entrypoint를 override 하지 않으면 아래 script 커맨드들이 실행되지 않음
entrypoint: [""]
before_script:
- mkdir -p /kaniko/.docker
- echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
- |
echo "-----BEGIN CERTIFICATE-----
##여기에 인증서 넣으면됨. 파일로 넣을라했는데 귀찮아서 kaniko 생성할때 인증서도 생성
-----END CERTIFICATE-----" >> /kaniko/ssl/certs/additional-ca-cert-bundle.crt
script:
# registry 접속 정보를 저장하기 위한 디렉토리 생성
- mkdir -p /kaniko/.docker
# Gitlab > Repository > Setting > CI/CD > Variables 사용
# variables에 저장해서 사용
# HARBOR_URL : harbor.example.com
# HARBOR_USER : username
# HARBOR_PASSWORD : userpassword
- echo "{\"auths\":{\"$HARBOR_URL\":{\"username\":\"$HARBOR_USER\",\"password\":\"$HARBOR_PASSWORD\"}}}" > /kaniko/.docker/config.json
# Gitlab에 미리 정의된 Variables 사용
# CI_PROJECT_DIR : Dockerfile을 포함한 Source Repositry 경로
# CI_COMMIT_SHORT_SHA : Commit SHA의 앞 8자를 tag로 사용
- /kaniko/executor --insecure --skip-tls-verify --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile --destination $HARBOR_URL/$CI_PROJECT_PATH:$CI_COMMIT_SHORT_SHA
helm-value-update:
stage: build
image:
name: alpine/git:latest
entrypoint: [""]
script:
- mkdir /helm-repo; cd /helm-repo
- git config --global http.sslVerify false
- git config --global user.name "louie0"
- git config --global user.email "louie0@xxx.com"
- git clone https://root:Softwiz%4012@gitlab.xxx.com/gitlab-instance-acb80999/helm-chart.git
# CI_COMMIT_SHORT_SHA 를 HELM values.yaml 파일 수정
- echo $CI_COMMIT_SHORT_SHA
- cd helm-chart; sh /helm-repo/helm-chart/tagging.sh
- git add .; git commit -m "tagging"; git push
only:
- main
-----------------------------------
Dockerfile
# 베이스 이미지 설정
FROM node:16
# Node.js 앱을 위한 app 폴더 생성
RUN mkdir -p /app
# 어플리케이션 폴더를 WORKDIR명령어로 지정 - 서버 가동용
WORKDIR /app
# 가능한 package.json 과 package-lock.json을 모두 복사하기 위해서 와일드 카드 사용
COPY package*.json /app/
# 의존성 설치
RUN npm install
# 앱 소스코드 추가
COPY app.js /app/
# 앱이 3000번 포트에 바인딩 되어있기 때문에 컨테이너의 3000번 포트를 열어줌
EXPOSE 3000
# 인자값을 지정하지 않을시 node app.js를 실행
CMD [ "node", "app.js" ]
그냥 node.js 이미지 불러오는 dockerfile 임.
-----------------------------
app.js
var express = require('express');
var app = express();
app.get('/', (req, res)=>{
res.send('<h1>hello Docker!</h1>')
});
app.listen(3000,'0.0.0.0',()=>{
console.log('Server Start : port 3000');
});
그냥 hello docker! 나오는 페이지 설정임
app.js를 수정하고 main 브랜치로 commit을 하게되면
이미지 빌드와 tagging 파이프라인이 동작하고
manifest repo 에 tag와 같은 tag를 가진 이미지가 harbor에 생성되고
위와 같이 argo cd를 통해 자동으로 배포가 된다.
추후 여러가지 배포(blue/green , canary)등 환경 구성하는것도 테스트 예정이다.
또한 egress 를 통해 외부연동되는부분도 테스트 예정이다.
'엔지니어 > Kubernetes' 카테고리의 다른 글
kubernetes 명령어 모음 (0) | 2023.11.06 |
---|---|
Harbor (0) | 2023.11.06 |
Helm (0) | 2023.11.06 |
Istio (0) | 2023.11.06 |
Calico CNI (0) | 2023.11.06 |