diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index fcff3a5..a761d0a 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -35,24 +35,11 @@ jobs: fi kubectl version --client - - name: Setup kubeconfig - env: - KUBECONFIG_CONTENT: ${{ secrets.KUBECONFIG }} + - name: Setup Kubernetes access run: | - mkdir -p $HOME/.kube - - if [ -z "$KUBECONFIG_CONTENT" ]; then - echo "❌ ERROR: KUBECONFIG secret is not set." - echo "Please add kubeconfig to Gitea Secrets with name 'KUBECONFIG'" - exit 1 - fi - - # Decode and save kubeconfig - echo "$KUBECONFIG_CONTENT" | base64 -d > $HOME/.kube/config - chmod 600 $HOME/.kube/config - - # Test connection - echo "Testing Kubernetes connection..." + # Running in Kubernetes Pod - use in-cluster config + echo "Running in Kubernetes - using ServiceAccount" + kubectl version kubectl get nodes -o wide - name: Lowercase repository name @@ -75,19 +62,16 @@ jobs: - name: Create Kaniko build context run: | - # Create tar.gz of build context - tar czf /tmp/build-context.tar.gz -C services/nextjs . - - # Create namespace if not exists - sudo kubectl get namespace kaniko-builds 2>/dev/null || sudo kubectl create namespace kaniko-builds + # Create namespace if not exists (will be created by ArgoCD, but check anyway) + kubectl get namespace kaniko-builds 2>/dev/null || kubectl create namespace kaniko-builds # Create/update registry credentials secret - sudo kubectl create secret docker-registry kaniko-registry-creds \ + kubectl create secret docker-registry kaniko-registry-creds \ --docker-server=${{ env.REGISTRY }} \ --docker-username=bluemayne \ --docker-password=${{ secrets.GITEAREGISTRY }} \ --namespace=kaniko-builds \ - --dry-run=client -o yaml | sudo kubectl apply -f - + --dry-run=client -o yaml | kubectl apply -f - - name: Build and push with Kaniko on Kubernetes id: build @@ -115,29 +99,29 @@ jobs: cat /tmp/kaniko-job.yaml # Apply the Job - sudo kubectl apply -f /tmp/kaniko-job.yaml + kubectl apply -f /tmp/kaniko-job.yaml # Wait for job to complete echo "⏳ Waiting for Kaniko job to complete..." - sudo kubectl wait --for=condition=complete --timeout=600s job/${BUILD_NAME} -n kaniko-builds || { + kubectl wait --for=condition=complete --timeout=600s job/${BUILD_NAME} -n kaniko-builds || { echo "❌ Job failed or timed out. Showing logs:" - POD=$(sudo kubectl get pods -n kaniko-builds -l job-name=${BUILD_NAME} -o jsonpath='{.items[0].metadata.name}') - sudo kubectl logs -n kaniko-builds ${POD} --all-containers=true || true - sudo kubectl delete job ${BUILD_NAME} -n kaniko-builds || true - sudo kubectl delete configmap ${BUILD_NAME}-dockerfile -n kaniko-builds || true + POD=$(kubectl get pods -n kaniko-builds -l job-name=${BUILD_NAME} -o jsonpath='{.items[0].metadata.name}') + kubectl logs -n kaniko-builds ${POD} --all-containers=true || true + kubectl delete job ${BUILD_NAME} -n kaniko-builds || true + kubectl delete configmap ${BUILD_NAME}-dockerfile -n kaniko-builds || true exit 1 } echo "✅ Image built successfully" # Get digest from logs - POD=$(sudo kubectl get pods -n kaniko-builds -l job-name=${BUILD_NAME} -o jsonpath='{.items[0].metadata.name}') - DIGEST=$(sudo kubectl logs -n kaniko-builds ${POD} -c kaniko 2>/dev/null | grep -oP 'digest: \K[a-zA-Z0-9:]+' | tail -1 || echo "unknown") + POD=$(kubectl get pods -n kaniko-builds -l job-name=${BUILD_NAME} -o jsonpath='{.items[0].metadata.name}') + DIGEST=$(kubectl logs -n kaniko-builds ${POD} -c kaniko 2>/dev/null | grep -oP 'digest: \K[a-zA-Z0-9:]+' | tail -1 || echo "unknown") echo "digest=${DIGEST}" >> $GITHUB_OUTPUT # Cleanup - sudo kubectl delete job ${BUILD_NAME} -n kaniko-builds || true - sudo kubectl delete configmap ${BUILD_NAME}-dockerfile -n kaniko-builds || true + kubectl delete job ${BUILD_NAME} -n kaniko-builds || true + kubectl delete configmap ${BUILD_NAME}-dockerfile -n kaniko-builds || true - name: Extract SHA tag id: extract-tag diff --git a/deploy/argocd/application-kaniko-infra.yaml b/deploy/argocd/application-kaniko-infra.yaml new file mode 100644 index 0000000..d115544 --- /dev/null +++ b/deploy/argocd/application-kaniko-infra.yaml @@ -0,0 +1,29 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: kaniko-infrastructure + namespace: argocd + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + project: default + source: + repoURL: https://gitea0213.kro.kr/bluemayne/jovies.git + targetRevision: main + path: deploy/kaniko + destination: + server: https://kubernetes.default.svc + namespace: kaniko-builds + syncPolicy: + automated: + prune: true + selfHeal: true + allowEmpty: false + syncOptions: + - CreateNamespace=true + retry: + limit: 5 + backoff: + duration: 5s + factor: 2 + maxDuration: 3m diff --git a/deploy/kaniko/kustomization.yaml b/deploy/kaniko/kustomization.yaml new file mode 100644 index 0000000..d502261 --- /dev/null +++ b/deploy/kaniko/kustomization.yaml @@ -0,0 +1,6 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: + - namespace.yaml + - rbac.yaml diff --git a/deploy/kaniko/namespace.yaml b/deploy/kaniko/namespace.yaml new file mode 100644 index 0000000..c1fdd16 --- /dev/null +++ b/deploy/kaniko/namespace.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: kaniko-builds + labels: + app.kubernetes.io/name: kaniko-builds + app.kubernetes.io/component: build-infrastructure diff --git a/deploy/kaniko/rbac.yaml b/deploy/kaniko/rbac.yaml new file mode 100644 index 0000000..6f76a3c --- /dev/null +++ b/deploy/kaniko/rbac.yaml @@ -0,0 +1,69 @@ +--- +# ServiceAccount for Gitea runner (optional, if you want dedicated SA) +apiVersion: v1 +kind: ServiceAccount +metadata: + name: gitea-runner + namespace: gitea +--- +# Role to manage Kaniko builds +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: kaniko-builder + namespace: kaniko-builds +rules: +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["create", "get", "list", "delete"] +- apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["pods/log"] + verbs: ["get"] +- apiGroups: ["batch"] + resources: ["jobs"] + verbs: ["create", "get", "list", "watch", "delete"] +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "create", "update", "patch"] +--- +# RoleBinding for default ServiceAccount in gitea namespace +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: gitea-runner-kaniko-builder + namespace: kaniko-builds +subjects: +- kind: ServiceAccount + name: default + namespace: gitea +roleRef: + kind: Role + name: kaniko-builder + apiGroup: rbac.authorization.k8s.io +--- +# ClusterRole to create namespaces (if needed) +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: namespace-creator +rules: +- apiGroups: [""] + resources: ["namespaces"] + verbs: ["create", "get", "list"] +--- +# ClusterRoleBinding for default ServiceAccount in gitea namespace +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: gitea-runner-namespace-creator +subjects: +- kind: ServiceAccount + name: default + namespace: gitea +roleRef: + kind: ClusterRole + name: namespace-creator + apiGroup: rbac.authorization.k8s.io