https://kubernetes.io/ko/docs/concepts/scheduling-eviction/assign-pod-node/
1. Affinity
Affinity 종류
1. NodeAffinity
어느 노드에 파드를 만들 것인지 선호도를 지정
1-1. anti-affinity
affinity의 반대, 선호하지 마라
2. PodAffinity
어느 파드에 컨테이너를 만들 것인지 선호도를 지정
선호도
1. required
선호되는 노드를 지정할 때 강제로 지정
2. preferred
선호되는 노드를 지정할 때 반강제로 지정(만들수도 있고 안만들수도 있다.)
가중치(weight)를 이용하여 비율적으로 분배되도록 지정 가능
연산자
1. In
value중에 하나라도 일치하면
2. NotIn
value중에 일치하는 게 없으면
3. Exists
존재한다면
key의 존재유무로 판단하기 때문에 value를 보지않는다.
4. doesNotExist
존재하지 않으면
5. GT
value보다 크면
6. LT
value보다 작으면
1) Node Affinity
1. Required
kubectl label nodes node1.k8s.local requiredkey=worknodereqkey
kubectl label nodes node2.k8s.local preferredkey2=worknodeprekey2
kubectl label nodes node3.k8s.local preferredkey3=worknodeprekey3
key 레이블을 각 노드에 입력
cat << EOF > pod-required-affinity-1.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-1
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: requiredkey
operator: In
values:
- worknodereqkey
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
EOF
연산자를 In으로 지정하여 실행하면 requiredkey라는 이름을 가진 key를 찾고 value값이 일치하는 노드에 대해 파드가 생성된다.
cat << EOF > pod-required-affinity-2.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-2
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: requiredkey
operator: Exists
# values:
# - worknodereqkey
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
EOF
연산자를 Exists으로 지정하여 실행하면 requiredkey라는 이름을 가진 key가 존재하면 해당 노드에 파드가 생성된다.
여기서 주의할 것은 Exists는 key가 있는지 검토만하고 실행하기 때문에 value를 보지않고 key의 존재유무만으로 파드를 생성한다.
2. Preferred
cat <<EOF > pod-preferred-affinity-1.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-3
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 20
preference:
matchExpressions:
- key: preferredkey2
operator: In
values:
- worknodeprekey2
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 30
preference:
matchExpressions:
- key: preferredkey3
operator: In
values:
- worknodeprekey3
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
EOF
가중치를 node2에는 20, node3에는 30을 주어 파드가 생성되는 선호도를 지정
cat<<EOF>pod-req-prefer-1.yaml
apiVersion: v1
kind: Pod
metadata:
name: with-affinity-1
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: requiredkey
operator: In
values:
- worknodereqkey
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: preferredkey2
operator: In
values:
- worknodeprekey2
- weight: 50
preference:
matchExpressions:
- key: preferredkey3
operator: In
values:
- worknodeprekey3
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
EOF
preferred보다 required가 우선된다.
2) Pod Affinity
cat <<EOF > pod-nginx-with-label-security.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
security: S1
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
EOF
파드에 "security: S1" 레이블을 지정
nginx-pod 가 node3에 생성되었다.
cat <<EOF > pod-nginx-with-label-security-node.yaml
apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: kubernetes.io/hostname
containers:
- name: with-pod-affinity
image: nginx
EOF
pod affinity로 키는 security, value는 S1인 파드가 있는 node3에 생성
topologyKey: kubernetes.io/hostname는 파드 어피니티 규칙을 적용할 때 호스트네임을 사용하여 파드를 스케줄링하는 것을 지정한다.
cat <<EOF > pod-nginx-with-label-anti-affinity.yaml
apiVersion: v1
kind: Pod
metadata:
name: with-pod-antiaffinity
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: kubernetes.io/hostname
containers:
- name: with-pod-antiaffinity
image: nginx
EOF
Security: S1 레이블을 가진 파드가 있는 node3이 아닌 곳에 파드를 생성해라는 뜻이다.
가중치(weight)는 100, 다시말해 node3에는 절대 생성하지 말라는 의미
아래 화면에 with-pod-antiaffinity가 node1에 생성됨을 볼 수 있다.
이것이 AntiAffinity
https://kubernetes.io/ko/docs/concepts/services-networking/network-policies/
2. 네크워크 정책
네트워크정책을 쉽게 방화벽이라 생각하면 된다.
stateless 개념을 가지고 있다.
예시
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
- Egress
ingress: # 들어오는 것
- from:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 6379
egress: # 나가는 것
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978
만약 내가 운영하고 있는 쿠버네티스에서 인그레스나 이그레스가 적용이 안된다면 위 사진을 참조
혹은 아래 방법 참조
1. 기존의 Flannel 삭제
기존의 Flannel을 유지한 상태로 Canal을 설치 시도 했지만 다양한 오류가 발생해서
일단은 Flannel을 삭제하고 진행함. 예상으로는 기존에 사용하던 Flannel version이 낮아서 문제가 발생한 것 같기도함.
[명령어]
kubectl delete -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
2. 모든 kubernetes Node docker restart
master node 를 포함한 모든 worker node의 docker를 restart 해줘야함
[명령어]
service docker restart
3. DataStore 종류 선택.
Calico 설치 방법은 Datastore에 종류에 따라서 etcd, kubernetes API Datastore 2가지로 나누어 짐.
Canal 설치 시에서도 DataStore를 선택해줘야함.
etcd
for direct connection to an etcd cluster
[장점]
1. 추가 DataStore가 필요하지 않으므로 관리가 더 간단함.
2. Kubernetes RBAC를 사용하여 Calico 리소스에 대한 액세스를 제어 할 수 있음.
3. Kubernetes audit logging을 사용하여 Calico 리소스 변경에 대한 audit logging를 생성 할 수 있음.
kubernetes API Datastore
for connection to a Kubernetes API server
[장점]
1. 비 Kubernetes 플랫폼 (예 : OpenStack)에서 Calico를 실행할 수 있음.
2. Kubernetes와 Calico 리소스 간의 문제를 분리 할 수 있음
3. Calico Cluster를 실행할 수 있음.
예제 환경에서는 kubernetes API Datastore으로 설치해보겠음.
4. Kube-Controller 모듈 Flag 설정
설정을 해야하지만 kubernetes 로컬 설치 과정에서 이미 했기 때문에 생략함.
참고 : 03. Kubernetes 로컬설치, 환경 예제 (Master Node 클러스터 구성 부분)
[명령어]
kubeadm init --pod-network-cidr=<your-pod-cidr>
5. Canal 설치 용 yaml파일을 Download
[명령어]
curl https://docs.projectcalico.org/manifests/canal.yaml -O
6. Canal 설치
[명령어]
kubectl apply -f canal.yaml
7. Flannel 설치
[명령어]
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
8. 모든 kubernetes Node docker restart
master node 를 포함한 모든 worker node의 docker를 restart 해줘야함
[명령어]
service docker restart
9. Canal 설치 확인
결과를 확인해보면 기존에 설치되어있던 Flannel 이 그대로 있으면서 Calico 가 추가된 것을 확인 할 수 있음.
[명령어]
kubectl get all -n kube-system
kubectl run app-pod --image=nginx
kubectl run web-pod --image=nginx
컨테이너 생성
kubectl expose pod app-pod --port=80
kubectl expose pod web-pod --port=80
80번 포트 개방
kubectl exec -it app-pod -- /bin/bash
접속이 되는지 확인
kubectl exec -it web-pod -- curl app-pod
외부에서 접근이 되는지 확인
cat <<EOF > default-deny.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
EOF
기본적으로 들어오는 것, 나가는 것 모두 차단
kubectl exec -it web-pod -- curl app-pod
kubectl exec -it app-pod -- curl web-pod
cat <<EOF > allow-egress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-egress
namespace: default
spec:
podSelector:
matchLabels:
run: app-pod
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
run: web-pod
EOF
위 정책을 적용하면 app에서 web으로 내보내는 것이 허용된다.
하지만 내보내는 것을 허용해봤자 들어오는 것부터 차단되어 있으므로 접근 불가
cat <<EOF > allow-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress
namespace: default
spec:
podSelector:
matchLabels:
run: web-pod
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
run: app-pod
EOF
위 정책을 적용하면 web에서 app으로 들어오는 것이 허용된다.
그래도 안된다.
이는 IP정보를 직접 명시해주면 해결이 가능하다.
일반적으로 pod과 pod 사이에서 통신할 때는 이름으로 통신이 가능하지만 현재 요청을 보내는 위치가 node이므로 이름으로 통신이 불가능하기때문에 IP를 명시해줘야 한다.
kubectl exec -it app-pod -- curl [web-pod의 IP]
정상적으로 응답을 받았다.
적용된 네트워크 정책이다.
허용해준 파드에 대해서 web은 app으로부터 요청을 받고 응답을 내보내는 것만 허용했기 때문에 당연히 역은 성립하지 않는다.
기존의 default-deny.yaml을 제외하고 모두 삭제한 뒤 실습
cat <<EOF > allow-egress-1.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-egress-1
namespace: default
spec:
podSelector:
matchLabels:
run: app-pod
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
run: web-pod
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-egress-2
namespace: default
spec:
podSelector:
matchLabels:
run: web-pod
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
run: app-pod
EOF
---
cat <<EOF > allow-ingress-1.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-1
namespace: default
spec:
podSelector:
matchLabels:
run: web-pod
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
run: app-pod
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-2
namespace: default
spec:
podSelector:
matchLabels:
run: app-pod
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
run: web-pod
EOF
---
cat<<EOF>network-policy-pods.yaml
apiVersion: v1
kind: Pod
metadata:
name: http-go-v1
labels:
app: http-go-v1
spec:
containers:
- name: http-go
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Pod
metadata:
name: http-go-v2
labels:
app: http-go-v2
spec:
containers:
- name: http-go
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Pod
metadata:
name: http-go-v3
labels:
app: http-go-v3
spec:
containers:
- name: http-go
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: http-go-v1
spec:
selector:
app: http-go-v1
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: http-go-v2
spec:
selector:
app: http-go-v2
ports:
- protocol: TCP
port: 80
targetPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: http-go-v3
spec:
selector:
app: http-go-v3
ports:
- protocol: TCP
port: 80
targetPort: 80
EOF
---
cat<<EOF>network-policy-pods-np.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: http-go-v1-ingress
namespace: default
spec:
podSelector:
matchLabels:
app: http-go-v1
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: http-go-v2 # http-go-v1은 http-go-v2로 부터 들어오는것 허용
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: http-go-v2-ingress
namespace: default
spec:
podSelector:
matchLabels:
app: http-go-v2
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: http-go-v3 # http-go-v2는 http-go-v3으로 부터 들어오는것 허용
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: http-go-v3-ingress
namespace: default
spec:
podSelector:
matchLabels:
app: http-go-v3 # http-go-v3은 어느곳으로 부터 들어오는것 허용안함
policyTypes:
- Ingress
EOF
3. Helm
centos의 yum, ubuntu의 apt와 같은 것이라 보면 된다.
1. 첫번째 방법
필자는 두번째 방법을 성공했으므로 실패하는 것을 보기 싫으면 두번째로 이동
wget https://get.helm.sh/helm-v3.3.0-linux-amd64.tar.gz
tar xvzf helm-v3.3.0-linux-amd64.tar.gz
cd linux-amd64/
mkdir /usr/local/bin/helm/
mv * /usr/local/bin/helm/
# 환경변수 설정 시 .bashrc파일의 제일 밑에 아래 PATH를 붙여넣고 source .bashrc해도 됨
PATH=$PATH:$HOME/bin:/usr/local/bin/helm
helm 명령을 쓰기 위한 절차
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add brigade https://brigadecore.github.io/charts
helm repo add stable https://charts.helm.sh/stable
레포지토리 추가
helm repo update
업데이트
helm search repo stable
helm search repo bitnami
레포지토리에서 사용가능한 내용들
helm repo add incubator https://charts.helm.sh/incubator
helm repo add mysql-operator https://mysql.github.io/mysql-operator/
새로운 레포지토리 추가
위에서 했던 모든 파드와 네트워크 폴리시를 지우고
mkdir helmcharts
cd helmcharts/
helm pull bitnami/nginx
tar xzvf nginx-15.2.0.tgz
※ more 와 less 의 차이
more : 읽기 전용
- nano, vi와 비슷
- v를 누르면 편집모드 진입
- /는 찾기
less : 읽기, 쓰기 가능
more values.yaml
# 파일 내부에 replicaCount: 1 을 3으로 고치고
helm install nginx -f values.yaml
하지만 에러가 뜬다.
아무래도 소스가 잘못된 것 같다.
원래대로 되돌리자.
rm -rf /usr/local/bin/helm
vi .bashrc
# 제일 밑에 PATH지정해놓은 것을 삭제 후 source .bashrc
echo $PATH
# PATH가 없어진 것을 확인
# 만약 여전히 존재하면 exit로 root에서 나갔다가 다시 sudo -i
# 나갔다가 다시 접속하면 임시로 저장되어있던 PATH들은 모두 사라짐
두번째 방법
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
apt install git make
# 아마 에러가 뜰 것이다.
# snap install go
# 보안상 문제로 --classic을 사용하도록 유도함.
snap install go --classic
# --classic 옵션을 주어 설치하면 된다.
git clone https://github.com/helm/helm.git
cd helm
make
위와 같이 설치 후
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add brigade https://brigadecore.github.io/charts
helm repo add stable https://charts.helm.sh/stable
helm repo add incubator https://charts.helm.sh/incubator
helm repo add mysql-operator https://mysql.github.io/mysql-operator/
레포지토리를 다시 추가
helm pull bitnami/nginx
tar xvfz nginx-15.2.0.tgz
bitnami/nginx 가져온 후
cd nginx
helm install nginx -f my-values.yaml .
nginx 제거
helm get manifest nginx # yaml를 볼 수 있음
helm uninstall nginx # 삭제
'Kubernetes' 카테고리의 다른 글
Kubernetes 기초 - Pod(1) (0) | 2023.12.06 |
---|---|
Kubernetes 기초 - 동작 원리 (0) | 2023.12.06 |
23.9.6(수) 쿠버네티스 8일차 (0) | 2023.09.06 |
23.9.4(월) 쿠버네티스 7일차 (0) | 2023.09.04 |
23.9.1(금) 쿠버네티스 6일차 (0) | 2023.09.01 |