티스토리 뷰
✅ 아래 글의 내용 및 이미지는 인프런 "쿠버네티스 어나더 클래스 (지상편) - Sprint 1, 2" 강의를 듣고 정리한 글입니다.
Kustomize
- Helm create 명령을 쓰면 기본으로 패키지 폴더가 만들어지는 것과 달리 Kustomize는 직접 폴더를 만들어야 한다.
- 폴더에 하위 폴더 구성도 직접 만들어야 한다. (공식 가이드에 잘 나와있음)
- 배포할 yaml 파일들도 직접 만들어 줘야한다.
- 폴더구조와 kustomization.yaml 파일의 기능만 알면 쉽다. Helm에 비해서는 알아야될 양이 적다!
- base 폴더가 helm의 templates 폴더와 동일한 폴더라고 생각하면 된다.
- kustomization.yaml 파일이 제일 중요한데 반복적으로 사용되는 속성에 대한 공통값을 설정할 수 있다.
- kustomize는 kustomization 파일에 리소스가 적혀있어서 내가 배포할 파일들만 명시적으로 정하면 된다.
- overlays 라는 폴더가 있는데 환경에 맞게 오버레이 될 파일들을 넣는 폴더다.
- 환경별 폴더에는 마찬가지로 kustomization 파일이 있는데 하는 역할은 같다.
- 만약 개발 환경을 배포하려면 `kubectl apply -k ./app/overlays/dev` 식으로 써주면 된다.
폴더 구조와 kustomization의 파일내용
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
commonLabels:
part-of: k8s-anotherclass
component: backend-server
name: api-tester
instance: api-tester-2222
managed-by: kustomize
resources:
- configmap.yaml
- deployment.yaml
- secret.yaml
- service.yaml
실습
1-1. item name 입력 및 Pipeline 선택
Enter an item name에 [2222-deploy-kustomize] 입력
Copy form에 [2221-deploy-helm] 입력
[OK] 버튼 클릭
1-2. Configure > Advanced Project Options > Pipeline
1-3-1. [저장] 후 [지금 빌드] 실행 후 [Abort] 그리고 [페이지 새로고침] 하기

* 최초 실행시엔 매개변수 입력 버튼이 안나옴 [dev, qa, prod]중 dev가 적용됨
1-3-2. [파라미터와 함께 빌드] 실행 후 PROFILE을 [dev]로 선택하고 [빌드하기] 클릭
1-3-3. [Stage View] 결과 확인
※ 배포 되기전 꼭 배포될 템플릿 Logs 확인하기
1-4. [파라미터와 함께 빌드] 실행 후 PROFILE을 [qa], [prod]로 선택하고 [빌드하기] 클릭 그리고 [대시보드] 확인
1-5. 디렉토리 설명
1-6. [배포 코드] 확인
https://github.com/k8s-1pro/kubernetes-anotherclass-sprint2/tree/main/2222
JenkinsFile
여기서 parameters에서 저렇게 파라미터를 넣는게 있어서 내용이 파라미터 빌드시 도커허브나 깃허브이름, 배포 환경을 선택하는게 뜨는것이었다!
pipeline {
agent any
tools {
gradle 'gradle-7.6.1'
jdk 'jdk-17'
}
parameters {
// 배포 환경 선택
choice(choices: ['dev', 'qa', 'prod'], name: 'PROFILE', description: '배포 환경 선택')
// DockerHub 사용자명 입력
string(name: 'DOCKERHUB_USERNAME', defaultValue: '', description: 'DockerHub 사용자명을 입력하세요.')
// GitHub 사용자명 입력
string(name: 'GITHUB_USERNAME', defaultValue: '', description: 'GitHub 사용자명을 입력하세요.')
}
environment {
// DOCKERHUB_USERNAME = ""
// GITHUB_USERNAME = ""
// 아래 부분 수정(x)
GITHUB_URL = "https://github.com/${GITHUB_USERNAME}/kubernetes-anotherclass-sprint2.git"
CLASS_NUM = '2222'
}
stages {
stage('Username 확인') {
steps {
script {
if (!env.DOCKERHUB_USERNAME?.trim() || !env.GITHUB_USERNAME?.trim()) {
error "[파라미터와 함께 빌드]에 GITHUB_USERNAME를 본인의 username으로 입력해 주세요! 매번 입력이 번거롭다면 Jenkinsfile에서 parameters에 입력 항목을 삭제 하시고 environment에 전역값을 넣은 후 해당 조건문은 삭제해 주세요. "
}
}
}
}
stage('소스파일 체크아웃') {
steps {
// 소스코드를 가져올 Github 주소
git branch: 'main', url: 'https://github.com/k8s-1pro/kubernetes-anotherclass-api-tester.git'
}
}
stage('소스 빌드') {
steps {
// 빌드 배포가 중요한 건 아니기 때문에 실제 실행되지 않도록 echo 명령을 사용
// 755권한 필요 (윈도우에서 Git으로 소스 업로드시 권한은 644)
echo "chmod +x ./gradlew"
echo "gradle clean build"
}
}
stage('릴리즈파일 체크아웃') {
steps {
checkout scmGit(branches: [[name: '*/main']],
extensions: [[$class: 'SparseCheckoutPaths',
sparseCheckoutPaths: [[path: "/${CLASS_NUM}"]]]],
userRemoteConfigs: [[url: "${GITHUB_URL}"]])
}
}
stage('컨테이너 빌드') {
steps {
// jar 파일 복사
echo "cp ./build/libs/app-0.0.1-SNAPSHOT.jar ./${CLASS_NUM}/build/docker/app-0.0.1-SNAPSHOT.jar"
// 도커 빌드
echo "docker build -t ${DOCKERHUB_USERNAME}/api-tester:v1.0.0 ./${CLASS_NUM}/build/docker"
}
}
stage('컨테이너 업로드') {
steps {
// DockerHub로 이미지 업로드
echo "docker push ${DOCKERHUB_USERNAME}/api-tester:v1.0.0"
}
}
stage('커스터마이즈 템플릿 확인') {
steps {
// K8S 배포
sh "kubectl kustomize ./${CLASS_NUM}/deploy/kustomize/api-tester/overlays/${params.PROFILE}"
}
}
stage('커스터마이즈 배포') {
steps {
// K8S 배포
input message: '배포 시작', ok: "Yes"
sh "kubectl apply -f ./${CLASS_NUM}/deploy/kubectl/namespace-${params.PROFILE}.yaml"
sh "kubectl apply -k ./${CLASS_NUM}/deploy/kustomize/api-tester/overlays/${params.PROFILE}"
}
}
}
}
1-7. 실습 후 정리
# namespace 삭제
kubectl delete ns anotherclass-222-dev
kubectl delete ns anotherclass-222-qa
kubectl delete ns anotherclass-222-prod
2. 다양한 배포 환경을 위한 Helm 배포하기 - 2223
2-1. item name 입력 및 Pipeline 선택
Enter an item name에 [2223-deploy-helm] 입력
Copy form에 [2222-deploy-kustomize] 입력
[OK] 버튼 클릭

2-2. Configure > Advanced Project Options > Pipeline
Definition > SCM > Branches to build > Additional Behaviours > Sparse Checkout paths > Path : 2223
Definition > Script Path : 2223/Jenkinsfile

2-3-1. [저장] 후 [지금 빌드] 실행 후 [Abort] 그리고 [페이지 새로고침] 하기


* 최초 실행시엔 매개변수 입력 버튼이 안나옴 [dev, qa, prod]중 dev가 적용됨
2-3-2. [파라미터와 함께 빌드] 실행 후 PROFILE을 [dev]로 선택하고 [빌드하기] 클릭
2-3-3. [Stage View] 결과 확인

※ 배포 되기전 꼭 배포될 템플릿 Logs 확인하기
2-4. [파라미터와 함께 빌드] 실행 후 PROFILE을 [qa], [prod]로 선택하고 [빌드하기] 클릭 그리고 [대시보드] 확인
2-5. 환경별 배포 설명
2-6. [배포 코드] 확인
https://github.com/sskim91/kubernetes-anotherclass-sprint2/blob/main/2223/Jenkinsfile
pipeline {
agent any
tools {
gradle 'gradle-7.6.1'
jdk 'jdk-17'
}
parameters {
// 배포 환경 선택
choice(choices: ['dev', 'qa', 'prod'], name: 'PROFILE', description: '배포 환경 선택')
// DockerHub 사용자명 입력
string(name: 'DOCKERHUB_USERNAME', defaultValue: '', description: 'DockerHub 사용자명을 입력하세요.')
// GitHub 사용자명 입력
string(name: 'GITHUB_USERNAME', defaultValue: '', description: 'GitHub 사용자명을 입력하세요.')
}
environment {
// DOCKERHUB_USERNAME = ""
// GITHUB_USERNAME = ""
// 아래 부분 수정(x)
GITHUB_URL = "https://github.com/${GITHUB_USERNAME}/kubernetes-anotherclass-sprint2.git"
CLASS_NUM = '2223'
}
stages {
stage('소스파일 체크아웃') {
steps {
// 소스코드를 가져올 Github 주소
git branch: 'main', url: 'https://github.com/k8s-1pro/kubernetes-anotherclass-api-tester.git'
}
}
stage('소스 빌드') {
steps {
// 빌드 배포가 중요한 건 아니기 때문에 실제 실행되지 않도록 echo 명령을 사용
// 755권한 필요 (윈도우에서 Git으로 소스 업로드시 권한은 644)
echo "chmod +x ./gradlew"
echo "gradle clean build"
}
}
stage('릴리즈파일 체크아웃') {
steps {
checkout scmGit(branches: [[name: '*/main']],
extensions: [[$class: 'SparseCheckoutPaths',
sparseCheckoutPaths: [[path: "/${CLASS_NUM}"]]]],
userRemoteConfigs: [[url: "${GITHUB_URL}"]])
}
}
stage('컨테이너 빌드') {
steps {
// jar 파일 복사
echo "cp ./build/libs/app-0.0.1-SNAPSHOT.jar ./${CLASS_NUM}/build/docker/app-0.0.1-SNAPSHOT.jar"
// 도커 빌드
echo "docker build -t ${DOCKERHUB_USERNAME}/api-tester:v1.0.0 ./${CLASS_NUM}/build/docker"
}
}
stage('컨테이너 업로드') {
steps {
// DockerHub로 이미지 업로드
echo "docker push ${DOCKERHUB_USERNAME}/api-tester:v1.0.0"
}
}
stage('헬름 템플릿 확인') {
steps {
// K8S 배포
sh "helm template api-tester-${CLASS_NUM} ./${CLASS_NUM}/deploy/helm/api-tester" +
" -f ./${CLASS_NUM}/deploy/helm/api-tester/values-${params.PROFILE}.yaml -n anotherclass-222-${params.PROFILE}"
// --set replicaCount='3' --set port='80' --set profile='dev' --set nodeport='32223'
}
}
stage('헬름 배포') {
steps {
input message: '배포 시작', ok: "Yes"
sh "kubectl apply -f ./${CLASS_NUM}/deploy/kubectl/namespace-${params.PROFILE}.yaml"
sh "helm upgrade api-tester-${CLASS_NUM} ./${CLASS_NUM}/deploy/helm/api-tester" +
" -f ./${CLASS_NUM}/deploy/helm/api-tester/values-${params.PROFILE}.yaml" +
" -n anotherclass-222-${params.PROFILE} --install" // --create-namespace
}
}
}
}
2-7. 실습 후 정리
# helm 조회
helm list -n anotherclass-222
# helm 삭제
helm uninstall -n anotherclass-222-dev api-tester-2223
helm uninstall -n anotherclass-222-qa api-tester-2223
helm uninstall -n anotherclass-222-prod api-tester-2223
# namespace 삭제
kubectl delete ns anotherclass-222-dev
kubectl delete ns anotherclass-222-qa
kubectl delete ns anotherclass-222-prod
배포 파이프라인 구축 후 마주하게 되는 고민들
- CI/CD 환경에 Jenkins가 컨테이너 빌드도해서 Docker Hub로 업로드도 하고 Helm 배포도 한다.
- Helm 배포에는 인증서가 필요하고 컨테이너도 도커허브로 업로드를 해야해서 사전에 로그인을 해놔야함.
- 이때 로그인을 하면 특정 디렉토리에 접속 정보가 들어있는 파일이 생긴다.
- 문제는 이 docker-config.json 파일이 암호화가 안되어 있음.
- kubeconfig 파일도 관리자 권한의 인증서이고 서버에 접속해서 누가 복사라도 해가면 관리자 권한으로 kubectl 명령어를 날릴 수 있음.
- 1차적으로 CI/CD 서버에 아무나 들어갈수 없게 접근 보안을 잘 해야함.
- 처리방법으로는 Jenkins에 들어가서 kubeconfig 파일이나 docker-config.json 파일을 Credential로 등록을 한다.
- 그럼 인증서를 암호화시킨 상태에서 사용할 수 있기 때문에 등록한 사람도 본인이 등록한 이후에는 내용을 볼 수 없다!
- Docker Credential Helpers라는 것도 검색해보기
- 해수편 때 public docker hub를 안쓰고 private docker registry를 써본다고 한다.
- 빌드를 계속 하다보면 CI/CD 서버에 컨테이너 이미지들이 계속 쌓이는데 컨테이너를 업로드 한 후에 이미지를 잘 삭제해주면 Jenkins가 디스크가 부족해지는 현상을 없앨 수 있다.
- helm은 네임스페이스 배포와 별도로 관리해주는게 좋다.
- helm에서 자주 쓰게되는 부가 기능중 배포 명령 뒤에 --wait 이라는 명령이 있다.
- 이 부분은 검색해서 찾아보기
- helm에서 배포를 진행해도 업그레이드가 진행되지 않는 경우가 있다. 왜?
- k8s는 새로 배포되는 deployment 파일의 template 폴더 밑으로 내용의 변경이 있어야지 업그레이드를 시작한다.
- 이럴때를 위해서 helm에서 제공해주는 기능이 있는데 Annotations로 새 배포시마다 랜덤값을 생성해주는 기능이 있다.
이미지 태그 관리와 Pull 정책 정리 (중요!)
- 도커 이미지를 관리할 때 이미지명 뒤에 버전 태그를 붙여서 사용함.
- 예: my-app:1.0.0, my-app:latest
- 과거에는 버전 태그 앞에 v를 붙여서 v1.0.0처럼 썼는데, 지금은 보통 v를 생략하는게 관례임.
- latest 태그는 별도의 넘버링 없이 가장 마지막에 빌드된 이미지를 의미함.
- 버전 관리 신경 안 쓰고 최신 버전을 받고 싶으면 latest로 받음.
- 개발 환경에서는 보통 자주 배포하고 계속 덮어쓰기 때문에 이미지 태그를 latest로 통일하는 경우가 많음.
- 하지만 운영/검증 환경에서는 각 기능이나 변경사항별로 확실하게 버전 태그를 명시해서 관리하는 게 일반적임.
- 그래야 롤백하거나 히스토리 추적이 쉬움.
이미지 Pull 정책(Pull Policy)에 따른 차이점
- K8s에서 파드가 어떤 방식으로 이미지를 가져올지 결정하는 속성: imagePullPolicy
- 주요 옵션 세 가지
- Always: 항상 도커 허브(혹은 registry)에서 이미지를 받아옴
- IfNotPresent: 노드에 이미지가 없을 때만 가져옴 (있으면 캐시된 이미지 사용)
- Never: 아예 허브에서 안 가져오고 무조건 로컬에 있는 이미지만 사용
- 개발 환경에서는 latest 태그로 배포하면서 imagePullPolicy: Always를 주는 게 일반적
- 이유: 항상 최신 이미지를 받고 싶기 때문
- 단점: 도커 허브에 연결 안 되면 파드가 생성되지 않음
- 반면 검증/운영 환경에서는 태그를 명시적으로 지정하고 IfNotPresent로 설정하는 게 좋음
- 이유: 노드에 캐시된 이미지가 있으면 굳이 또 받지 않아서 효율적
- 파드가 스케일 업/다운될 때 매번 pull하면 비효율 + 느려질 수 있음
- 핵심:
- latest 쓸 거면 → Always
- 명시적 태그 쓸 거면 → IfNotPresent
- 실무에서 문제가 되는 상황:
- imagePullPolicy: IfNotPresent인데 도커 허브에서 이미지를 갱신했을 경우,
- 기존 노드에 남아있는 예전 버전 이미지가 재사용돼서 문제가 발생할 수 있음.
- 그래서 latest를 쓸 경우 반드시 Always를 같이 써줘야 함.
3. 배포 파이프라인 구축 후 마주하게 되는 고민들 2224
이 부분은 나중에 실습해보자...너무졸리다.
3-1. item name 입력 및 Pipeline 선택
Enter an item name에 [2224-deploy-helm] 입력
Copy form에 [2223-deploy-helm] 입력
[OK] 버튼 클릭

3-2. Configure > Advanced Project Options > Pipeline
Definition > SCM > Branches to build > Additional Behaviours > Sparse Checkout paths > Path : 2224
Definition > Script Path : 2224/Jenkinsfile

3-3. 배포 파이프라인 구축 후 마주하게 되는 고민들

3-3-1. 중요 데이터 암호화 관리
3-3-1-1. 도커 접속 정보 및 쿠버네티스 config를 위한 New credentials 생성
- Dashboard > Jenkins 관리 > Credentials > System > Global credentials (unrestricted) 에서 [Add Credentials] 클릭

Global Credentials 클릭

● Docker 접속정보 Credentials 등록

카페에 적혀있는 내용대로 등록

● Kubernetes config 파일 Credentials 등록
* [파일 선택]을 위해 사전에 CI/CD Server에 있는 config 파일을 내 PC로 복사해 놓아야 합니다.
# config 파일 위치
[jenkins@cicd-server .kube]$ pwd
/var/lib/jenkins/.kube
[jenkins@cicd-server .kube]$ ls
cache config
* Windows에서 이동 방법 : /var/lib/jenkins/.kube/를 입력 후 config 파일이 나오면 내 PC 바탕화면으로 드래그 하시면 되요.
* Mac에서 이동 방법 : scp root@192.168.56.30:/var/lib/jenkins/.kube/config ~/Desktop/k8s-master-config

전체 등록 파일 화면

3-3-1-2. Jenkinsfile 내용
// Docker 사용
steps {
script{
withCredentials([usernamePassword(credentialsId: 'docker_password', passwordVariable: 'PASSWORD', usernameVariable: 'USERNAME')]) {
sh "echo " + '${PASSWORD}' + " | docker login -u " + '${USERNAME}' + " --password-stdin"
// Kubernetes config 사용
steps {
withCredentials([file(credentialsId: 'k8s_master_config', variable: 'KUBECONFIG')]) { // 암호화로 관리된 config가 들어감
sh "kubectl apply -f ./2224/deploy/kubectl/namespace-dev.yaml --kubeconfig " + '${KUBECONFIG}'
sh "helm upgrade api-tester-2224 ./2224/deploy/helm/api-tester -f ./2224/deploy/helm/api-tester/values-dev.yaml" +
" -n anotherclass-222-dev --install --kubeconfig " + '${KUBECONFIG}'
3-3-1-3. CI/CD Server에서 Docker Logout 및 kubeconfig 삭제
# Docker Hub Logout 하기
[jenkins@cicd-server ~]$ docker logout
Removing login credentials for https://index.docker.io/v1/
[jenkins@cicd-server .docker]$ cat ~/.docker/config.json
{
"auths": {}
}
# kubeconfig 파일명 변경하기
[jenkins@cicd-server ~]$ mv ~/.kube/config ~/.kube/config_bak
[jenkins@cicd-server ~]$ kubectl get pods -A
E1219 17:16:27.450820 3778 memcache.go:265] couldn't get current server API group list: <html>...
3-3-2. 잦은 배포 - Versioning 무의미, 계획된 배포 - Versioning 필수 - Jenkinsfile 내용
environment {
APP_VERSION = '1.0.1'
BUILD_DATE = sh(script: "echo `date +%y%m%d.%d%H%M`", returnStdout: true).trim()
// 위에 date 포맷 오류가 있어요. %y%m%d.%H%M%S가 맞습니다)
TAG = "${APP_VERSION}-" + "${BUILD_DATA}"
stage('컨테이너 빌드 및 업로드') {
steps {
script{
// 도커 빌드
sh "docker build ./2224/build/docker -t 1pro/api-tester:${TAG}"
sh "docker push 1pro/api-tester:${TAG}"
stage('헬름 배포') {
steps {
withCredentials([file(credentialsId: 'k8s_master_config', variable: 'KUBECONFIG')]) {
sh "helm upgrade api-tester-2224 ./2224/deploy/helm/api-tester -f ./2224/deploy/helm/api-tester/values-dev.yaml" +
...
" --set image.tag=${TAG}" // Deployment의 Image에 태그 값 주입
* docker tag 변경 명령 (to latest)
docker tag 1pro/api-tester:1.0.1-231220.171834 1pro/api-tester:latest
docker push 1pro/api-tester:latest
3-3-3. 업로드 후 CI/CD Server에 만들어진 이미지 삭제 - Jenkinsfile 내용
stage('컨테이너 빌드 및 업로드') {
steps {
script{
// 도커 빌드
sh "docker build ./${CLASS_NUM}/build/docker -t ${DOCKERHUB_USERNAME}/api-tester:${TAG}"
sh "docker push ${DOCKERHUB_USERNAME}/api-tester:${TAG}"
sh "docker rmi ${DOCKERHUB_USERNAME}/api-tester:${TAG}" // 이미지 삭제
3-3-4.네임스페이스는 배포와 별도로 관리 - Jenkinsfile 내용
stage('네임스페이스 생성') { // 배포시 apply로 Namespace 생성 or 배포와 별개로 미리 생성 (추후 삭제시 별도 삭제)
steps {
withCredentials([file(credentialsId: 'k8s_master_config', variable: 'KUBECONFIG')]) {
sh "kubectl apply -f ./2224/deploy/kubectl/namespace-dev.yaml --kubeconfig " + '"${KUBECONFIG}"'
...
stage('헬름 배포') {
steps {
3-3-5-1. Helm 부가기능 (배포 후 Pod 업그레이드가 안될 수 있음) - deployment.yaml 내용
apiVersion: apps/v1
kind: Deployment
spec:
template:
metadata:
annotations:
rollme: {{ randAlphaNum 5 | quote }} // 항상 새 배포를 위해 랜덤값 적용
3-3-5-2. Helm 부가기능 (Pod가 완전 기동 될때까지 결과값 기다림) - helm command 명령어 내용
stage('헬름 배포') {
steps {
withCredentials([file(credentialsId: 'k8s_master_config', variable: 'KUBECONFIG')]) {
sh "helm upgrade api-tester-2224 ./2224/deploy/helm/api-tester -f ./2224/deploy/helm/api-tester/values-dev.yaml" +
...
" --wait --timeout=10m" + // 최대 10분으로 설정
3-3-6. 사용 안하는 이미지는 자동 삭제됨 - config.yaml 내용
// GC 속성 추가하기
[root@k8s-master ~]# vi /var/lib/kubelet/config.yaml
-----------------------------------
imageMinimumGCAge : 3m // 이미지 생성 후 해당 시간이 지나야 GC 대상이 됨 (Default : 2m)
imageGCHighThresholdPercent : 80 // Disk가 80% 위로 올라가면 GC 수행 (Default : 85)
imageGCLowThresholdPercent : 70 // Disk가 70% 밑으로 떨어지면 GC 수행 안함(Default : 80)
-----------------------------------
// kubelet 재시작
[root@k8s-master ~]# systemctl restart kubelet
* Kubernetes docs : https://kubernetes.io/docs/concepts/architecture/garbage-collection/
3-4. [파라미터와 함께 빌드] 실행 후 PROFILE을 [dev]로 선택하고 [빌드하기] 클릭

3-5. 실습 후 정리
# helm 조회
helm list -n anotherclass-222
# helm 삭제
helm uninstall -n anotherclass-222-dev api-tester-2224
helm uninstall -n anotherclass-222-qa api-tester-2224
helm uninstall -n anotherclass-222-prod api-tester-2224
# namespace 삭제
kubectl delete ns anotherclass-222-dev
kubectl delete ns anotherclass-222-qa
kubectl delete ns anotherclass-222-prod
출처
쿠버네티스 어나더 클래스 (지상편) - Sprint 1, 2 강의 | 일프로 - 인프런
일프로 | , ✅ 광범위한 쿠버네티스 기술을 A~Z까지 넓고 얇게 훑기보다 하나의 개념을 배우더라도 왜 사용하는지 부터 실무에서 어떻게 사용되는지 까지를 다루는 강의✅ 시작은 초급자지만강
www.inflearn.com
https://cafe.naver.com/kubeops/104
Helm과 Kustomize 비교하며 사용하기 (2/2)
패키지 구조 비교 배포 파이프라인 구축 후 마주하게 되는 고민들 1. 다양한 배포 환경을 위한 Kustomize 배포하기 - 2222 1-1. item name 입력 및 Pi...
cafe.naver.com
- Total
- Today
- Yesterday
- input
- k8s
- 베리 심플
- Mac
- intellij
- config-location
- oracle
- maven
- mybatis
- Java
- mybatis config
- Spring Security
- docker
- 북리뷰
- LocalDate
- localtime
- JavaScript
- rocky
- Bash tab
- elasticsearch
- svn
- Spring
- window
- Linux
- jQuery
- 오라클
- springboot
- claude
- Kotlin
- LocalDateTime
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |