Kubernetes yaml 파일로 동적 값을 설정하는 방법
Kubernetes yaml 파일로 동적 값을 설정하는 방법
예를 들어, 배포 yaml 파일:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: guestbook
spec:
replicas: 2
template:
metadata:
labels:
app: guestbook
spec:
container:
- name: guestbook
image: {{Here want to read value from config file outside}}
Kubernetes에 대한 기능이 있지만, 그것도 yaml 파일에 키/값을 쓰는 것이다. 환경 변수의 키를 설정하는 방법이 있나요?
나는 쿠버네테스에서 변수나 Config Map을 통해 이미지를 설정하는 것은 불가능하다고 생각한다. 그러나 예를 들어, 훨씬 더 유연하고 구성 가능한 배포 환경을 만들 수 있습니다.
자동으로 할 수 없으며, 템플릿을 "컴파일"하기 위해 외부 스크립트를 사용하거나 @Jakub이 제안한 대로 조타를 사용해야 합니다.
CI 파이프라인과 통합된 사용자 지정 bash 스크립트를 사용할 수 있습니다.
제공한 파일과 매우 유사한 템플릿 yml 파일을 지정하면 다음과 같은 것을 사용할 수 있습니다:
#!/bin/bash
# sample value for your variables
MYVARVALUE="nginx:latest"
# read the yml template from a file and substitute the string
# {{MYVARNAME}} with the value of the MYVARVALUE variable
template=`cat "deploy.yml.template" | sed "s/{{MYVARNAME}}/$MYVARVALUE/g"`
# apply the yml with the substituted value
echo "$template" | kubectl apply -f -
내 접근 방식:
:
#!/usr/bin/env python3
import os
import sys
from jinja2 import Environment, FileSystemLoader
sys.stdout.write(Environment(loader=FileSystemLoader('templates/')).from_string(sys.stdin.read()).render(env=os.environ) + "\n")
규칙 만들기:
_GENFILES = $(basename $(TEMPLATES))
GENFILES = $(_GENFILES:templates/%=%)
$(GENFILES): %: templates/%.j2 $(MKFILES) tools/jinja2-cli.py .env
env $$(cat .env | xargs) tools/jinja2-cli.py < $< > $@ || (rm -f $@; false)
템플릿 파일 내에서 모든 jinja 구문 구조를 사용할 수 있습니다. 예를 들어, 에서 정의된 값으로 대체됩니다
그래서 당신은 다음과 같이 보일 것이다:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: guestbook
spec:
replicas: 2
template:
metadata:
labels:
app: guestbook
spec:
container:
- name: guestbook
image: {{env.GUEST}}
다른 접근 방식(기본 제공 및 사용)은 다음과 같습니다
env $(cat .env | xargs) cat <<EOF | kubectl create -f -
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: guestbook
spec:
replicas: 2
template:
metadata:
labels:
app: guestbook
spec:
container:
- name: guestbook
image: ${GUEST}
EOF
한 줄:
cat app-deployment.yaml | sed "s/{{BITBUCKET_COMMIT}}/$BITBUCKET_COMMIT/g" | kubectl apply -f -
yaml 단위:
...
containers:
- name: ulisses
image: niceuser/niceimage:{{BITBUCKET_COMMIT}}
...
라는 스크립트를 생성하고 이 스크립트를 사용하여 create 명령을 실행합니다. 환경 변수에서 참조되는 템플릿의 모든 값을 대체합니다.
#!/bin/bash
set -e
eval "cat <<EOF
$(<$1)
EOF
" | kubectl create -f -
예를 들어 템플릿 파일에 다음이 포함되어 있는 경우:
apiVersion: v1
kind: Service
metadata:
name: nginx-external
labels:
app: nginx
spec:
loadBalancerIP: ${PUBLIC_IP}
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
selector:
app: nginx
실행 후 실제 kubectl create 명령을 실행하기 전에 환경 변수 PUBLIC_IP가 대체됩니다.
배포할 때 를 사용할 수도 있습니다.
예.
cat app/deployment.yaml | envsubst | kubectl apply ...
파일의 모든 변수를 해당 값으로 바꿉니다. NAT은 여러 환경에 배포할 때 이 접근 방식을 CI에서 성공적으로 사용하고 있으며, 배포에 등을 주입하고 있습니다.
나는 사용해 왔다
세 가지 템플릿 맛이 있으며 ConfigMap/Secret freezing을 지원합니다.
이런 종류의 것은 고통스러울 정도로 쉽다:
deployment.yml
#@ load("@ytt:data", "data")
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: guestbook
spec:
replicas: 2
template:
metadata:
labels:
app: guestbook
spec:
container:
- name: guestbook
image: #@ data.values.image
values.yml
#@data/values
image: nginx@sha256:fe2fa7bb1ceb86c6d9c935bc25c3dd8cbd64f2e95ed5b894f93ae7ffbd1e92bb
그럼...
$ ytt -f deployment.yml -f values.yml | kubectl apply -f -
더 나은 방법은 의 사촌을 사용하여 높은 수준의 구축 환경을 구축하는 것입니다:
$ ytt -f deployment.yml -f values.yml | kapp deploy -a guestbook -f -
배포가 실행되는 동안 이미지 또는 태그만 변경하려는 경우 배포에 포함된 특정 컨테이너의 이미지를 설정할 수 있습니다:
kubectl apply -f k8s
kubectl set image deployments/worker-deployment worker=IMAGE:TAG
jitsi 프로젝트에서 == 명령어는 값을 대체하는 데 사용됩니다
https://github.com/jitsi/docker-jitsi-meet/issues/65
나는 sed나 friends와 같은 오래된 셸 도구를 계속 사용하지만 그러한 코드는 처리해야 할 소수의 가치 이상일 때 빠르게 읽을 수 없다.
나는 요즘 이 문제를 해결하기 위해 맞춤형 스크립트 대신 표준 - 헬름을 사용해야 한다고 생각한다. 기계에서 쿠버네츠 얌을 생성하기 위해 배치할 필요는 없습니다.
예:
명령이 존재하도록 기계에 조타 장치를 설치합니다
- 설치 단추
helm repo add pauls-helm-charts http://tech.paulcz.net/charts
helm pull pauls-helm-charts/helloworld --version 2.0.0
tar -zxvf helloworld-2.0.0.tgz && cd helloworld
helm template -f values.yaml --output-dir helloworld . --namespace my-namespace --name-template=my-name
그래서 이 파일들을 다음에서 만들었다:
wrote helloworld/helloworld/templates/serviceaccount.yaml
wrote helloworld/helloworld/templates/service.yaml
wrote helloworld/helloworld/templates/deployment.yaml
내부에서 사전 정의된 값을 변경할 수 있습니다(또는 원하는 대로 Kubernetes yamls에서 100% 임의의 값을 반복할 수 있습니다):
image:
repository: paulczar/spring-helloworld
이제 배포하려면 제대로 작동하는지 확인하고 등을 사용하여 생성된 파일을 적용하십시오.
아래와 같이 파일을 만들고 kubectl 명령어처럼 즐겨 불러요.
예.
EXPORT MY_VAL="my-v1"
kubectl_advance -c -f sample.yaml # -c option is to call create command
kubectl_advance -r -f sample2.yaml # -r option is to call replace command
yaml 파일의 ${MY_VAL}과 같은 값이 환경 변수로 대체된다고 가정합니다.
#!/usr/bin/env bash
helpFunction()
{
echo "Supported option is [-f] for file"
exit 1
}
while getopts "f:cr" opt
do
case "$opt" in
f ) yamlFile="$OPTARG" ;;
c ) COMMAND_IS_CREATE="true" ;;
r ) COMMAND_IS_REPLACE="true" ;;
? ) helpFunction ;; # Print helpFunction in case parameter is non-existent
esac
done
echo 'yaml file is : '$yamlFile
YAML_CONTENT=`eval "cat <<EOF
$(<$yamlFile)
EOF
"`
echo 'Final File Content is :=>'
echo '------------------'
echo "$YAML_CONTENT"
if [[ "$COMMAND_IS_CREATE" == "true" ]]; then
COMMAND="create"
fi
if [[ "$COMMAND_IS_REPLACE" == "true" ]]; then
COMMAND="replace"
fi
echo "$YAML_CONTENT" | kubectl $COMMAND -f -
시도한 후에 나는 가장 우아하고 쿠베르네테스 고유의 방법을 찾았다. 대안으로서 또한 때때로 유용하다.
Kustomize를 사용하여 이미지 이름 변경
CLI(예: Mac의 경우 )를 사용하여 다음과 같은 디렉토리에 새 파일을 만듭니다:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
이제 명령을 사용하여 이미지 이름을 변경합니다
# optionally define image name
IMAGE_NAME=ghcr.io/yourrepo/guestbook:c25a74c8f919a72e3f00928917dc4ab2944ab061
# replace image tag
kustomize edit set image $IMAGE_NAME
마지막으로 다음과 같은 방법을 사용하여 맞춤형을 클러스터에 적용합니다:
kubectl apply -k .
디버깅의 경우 다음을 실행하면 결과를 볼 수 있습니다:
$ kustomize build .
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: guestbook
spec:
replicas: 2
template:
metadata:
labels:
app: guestbook
spec:
containers:
- image: ghcr.io/yourrepo/guestbook:c25a74c8f919a72e3f00928917dc4ab2944ab061
name: guestbook
대안: yq를 사용하여 이미지 이름 변경
(예: 홈브루를 통해) 변수를 정의하고 yq가 대체를 수행하도록 합니다:
# define image name
IMAGE_NAME=ghcr.io/yourrepo/guestbook:c25a74c8f919a72e3f00928917dc4ab2944ab061
# replace image tag
yq e ".spec.template.spec.containers[0].image = \"$IMAGE_NAME\"" -i deployment.yaml
이제 새로운 이미지 버전이 생성되고 다음과 같이 표시됩니다:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: guestbook
spec:
replicas: 2
template:
metadata:
labels:
app: guestbook
spec:
containers:
- image: ghcr.io/yourrepo/guestbook:c25a74c8f919a72e3f00928917dc4ab2944ab061
name: guestbook
참고: 당신은 정말로 유효한 쿠버네티스 구성이 아닙니다. - 는 태그 아래에 있으면 안 됩니다. - 또한 철자도 있습니다.
배포의 경우 일반적으로 Helm 차트를 사용합니다. values.yaml 파일을 주기적으로 업데이트해야 합니다.
YAML 파일을 동적으로 업데이트하기 위해 'envsubst'를 사용했는데, 단순하고 정교한 구성이 필요하지 않기 때문입니다. 또한 대부분의 도구는 단순한 YAML 파일이 아닌 유효한 Kubernetes 매니페스트에서만 작동합니다.
나는 사용을 단순화하기 위해 YAML 수정을 처리하기 위한 간단한 스크립트를 만들었다
https://github.com/alexusarov/vars_replacer
예:
./vars_replacer.sh -i [input_file] -o [output_file] -p "[key=value] [key=value]"
, 그럴 방법은 없지만...
이것은 yq의 경우에 가능하다.
... 청소 및 :
cat <<EOF | yq 'explode(.)' | kubectl apply -f -
kind: Namespace
apiVersion: v1
metadata:
name: &namespace example-namespace
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: example-deployment
namespace: *namespace
spec:
replicas: 1
template:
metadata:
labels:
app: &app-label example-app
spec:
containers:
- name: httpecho
image: hashicorp/http-echo:0.2.3
args:
- "-listen=:5678"
- "-text=hello world 1"
ports:
- containerPort: &app-port 5678
selector:
matchLabels:
app: *app-label
---
kind: Service
apiVersion: v1
metadata:
name: &app-cluster-ip example-service
namespace: *namespace
spec:
type: ClusterIP
selector:
app: *app-label
ports:
- name: http
protocol: TCP
port: *app-port
targetPort: *app-port
---
kind: Ingress
apiVersion: networking.k8s.io/v1
metadata:
name: example-ingress
namespace: *namespace
spec:
ingressClassName: caddy
rules:
- host: example.kubernetes.localhost
http:
paths:
- path: /hello
pathType: Prefix
backend:
service:
name: *app-cluster-ip
port:
number: *app-port
EOF
나는 kubectl_apply라는 스크립트를 만듭니다. .env에서 변수를 로드하고 ${CUSTOMVAR}을(를) yml로 바꾼 다음 kubectl 명령으로 전달합니다
#!/bin/bash
set -a
source .env
set +a
eval "cat <<EOF
$(<$1)
EOF
" | kubectl apply -f -
헬름은 정확히 그런 것들과 더 많은 것들을 위한 것이다. 복잡한 리소스 배포 세트를 그룹 등으로 처리합니다.
하지만 우리가 여전히 간단한 대안을 찾고 있다면 개미를 사용하는 것은 어떨까요?
빌드 프로세스 또는 테스트 프로세스의 일부로 파일을 수정하려면 개미 작업도 수행할 수 있습니다.
개미를 사용하면 모든 환경 값을 속성으로 로드하거나 다음과 같은 속성 파일을 간단히 로드할 수 있습니다:
<property environment="env" />
<property file="build.properties" />
그런 다음 템플릿 파일을 원하는 yaml 파일로 변환하는 대상을 가질 수 있습니다.
<target name="generate_from_template">
<!-- Copy task to replaces values and create new file -->
<copy todir="${dest.dir}" verbose="true" overwrite="true" failonerror="true">
<!-- List of files to be processed -->
<fileset file="${source.dir}/xyz.template.yml" />
<!-- Mapper to transform filename. Removes '.template' from the file
name when copying the file to output directory -->
<mapper type="regexp" from="(.*).template(.*)" to="\1\2" />
<!-- Filter chain that replaces the template values with actual values
fetched from properties file -->
<filterchain>
<expandproperties />
</filterchain>
</copy>
</target>
물론 여러 파일(내포된 파일 등)에 대한 값을 동적으로 변경하려는 경우 대신 를 사용할 수 있습니다
템플릿 파일은 다음과 같아야 합니다:
apiVersion: v1
kind: Service
metadata:
name: ${XYZ_RES_NAME}-ser
labels:
app: ${XYZ_RES_NAME}
version: v1
spec:
type: NodePort
ports:
- port: ${env.XYZ_RES_PORT}
protocol: TCP
selector:
app: ${XYZ_RES_NAME}
version: v1
속성은 환경 변수에서 로드되고 기타 속성 파일에서 로드됩니다
도움이 되었기를 바랍니다 :)
스크립트를 작성할 계획이 있을 경우에 대비하여 이에 정확히 도움이 되는 명령줄 도구를 게시했습니다.
yaml은 다른 yaml 파일에서 값을 읽지 않습니다. 대안적인 접근법으로 이것을 시도할 수 있습니다.
kind: Pod
metadata:
creationTimestamp: null
annotations:
namespace: &namespaceId dev
imageId: &imgageId nginx
podName: &podName nginx-pod
containerName: &containerName nginx-container
name: *podName
namespace: *namespaceId
spec:
containers:
- image: *imgageId
name: *containerName
resources: {}
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}