From 04c8ab7489f14214de1c929498a5917f05829d43 Mon Sep 17 00:00:00 2001 From: Masaki Yatsu Date: Thu, 21 Aug 2025 16:56:16 +0900 Subject: [PATCH] feat(k8s): add private container registry --- env/justfile | 1 + k8s/justfile | 120 ++++++++++++++++++++++++++ k8s/registry/registries.gomplate.yaml | 4 + k8s/registry/registry.yaml | 84 ++++++++++++++++++ 4 files changed, 209 insertions(+) create mode 100644 k8s/registry/registries.gomplate.yaml create mode 100644 k8s/registry/registry.yaml diff --git a/env/justfile b/env/justfile index 4d71eda..487301a 100644 --- a/env/justfile +++ b/env/justfile @@ -9,6 +9,7 @@ export CONTAINER_REGISTRY_SERVER := env("CONTAINER_REGISTRY_SERVER", "") export CONTAINER_REGISTRY_USERNAME := env("CONTAINER_REGISTRY_USERNAME", "") export CONTAINER_REGISTRY_PASSWORD := env("CONTAINER_REGISTRY_PASSWORD", "") export CONTAINER_REGISTRY_EMAIL := env("CONTAINER_REGISTRY_EMAIL", "") +export K3S_ENABLE_REGISTRY := env("K3S_ENABLE_REGISTRY", "false") # Check if environment variables are set check: diff --git a/k8s/justfile b/k8s/justfile index ac748d0..48c5512 100644 --- a/k8s/justfile +++ b/k8s/justfile @@ -5,6 +5,7 @@ export EXTERNAL_K8S_HOST := env("EXTERNAL_K8S_HOST", "") export KEYCLOAK_HOST := env("KEYCLOAK_HOST", "") export KEYCLOAK_REALM := env("KEYCLOAK_REALM", "buunstack") export K8S_OIDC_CLIENT_ID := env('K8S_OIDC_CLIENT_ID', "k8s") +export K3S_ENABLE_REGISTRY := env("K3S_ENABLE_REGISTRY", "true") [private] default: @@ -42,6 +43,32 @@ install: fi echo "Running: k3sup ${args[*]}" k3sup "${args[@]}" + + if [ "${K3S_ENABLE_REGISTRY}" = "true" ]; then + echo "Setting up local Docker registry..." + + # Deploy Docker registry to cluster + kubectl apply -f ./registry/registry.yaml + + # Wait for registry deployment + echo "Waiting for registry to be ready..." + kubectl wait --for=condition=available --timeout=60s deployment/registry -n registry + + # Configure registries.yaml for k3s + just configure-registry + + echo "✓ Local Docker registry deployed and configured" + echo "" + echo "Registry accessible at:" + echo " localhost:30500" + echo "" + echo "Usage:" + echo " export DOCKER_HOST=ssh://${LOCAL_K8S_HOST}" + echo " docker build -t localhost:30500/myapp:latest ." + echo " docker push localhost:30500/myapp:latest" + echo " kubectl run myapp --image=localhost:30500/myapp:latest" + fi + echo "k3s cluster installed on ${LOCAL_K8S_HOST}." # Uninstall k3s cluster @@ -151,3 +178,96 @@ copy-regcred namespace: kubectl get -n default secret regcred -o json | \ sed "s/\"namespace\": \"default\"/\"namespace\": \"{{ namespace }}\"/g" | \ kubectl apply -n {{ namespace }} -f - + +# Check local Docker registry status +check-registry: + #!/bin/bash + set -euo pipefail + echo "Checking local Docker registry status..." + echo "" + + # Check if registry deployment exists + echo "1. Registry deployment status:" + if kubectl get deployment registry -n registry &>/dev/null; then + echo "✓ Registry deployment exists" + kubectl get deployment registry -n registry + echo "" + echo "Registry pods:" + kubectl get pods -n registry -l app=registry + else + echo "✗ Registry deployment not found" + fi + echo "" + + # Check registry services + echo "2. Registry services:" + if kubectl get service registry -n registry &>/dev/null; then + echo "✓ Registry service exists" + kubectl get service registry registry-nodeport -n registry + else + echo "✗ Registry services not found" + fi + echo "" + + # Check k3s registries configuration + echo "3. K3s registries configuration:" + if ssh "${LOCAL_K8S_HOST}" "sudo test -f /etc/rancher/k3s/registries.yaml"; then + echo "✓ Registries configuration exists" + ssh "${LOCAL_K8S_HOST}" "sudo cat /etc/rancher/k3s/registries.yaml" + else + echo "✗ Registries configuration not found" + fi + echo "" + + # Test registry accessibility + echo "4. Registry accessibility test:" + echo "Testing from k3s host (localhost:30500):" + if ssh "${LOCAL_K8S_HOST}" "curl -f -s http://localhost:30500/v2/" &>/dev/null; then + echo "✓ Registry is accessible from k3s host" + # Show registry catalog + echo "Registry catalog:" + ssh "${LOCAL_K8S_HOST}" "curl -s http://localhost:30500/v2/_catalog" 2>/dev/null || \ + echo "Unable to retrieve catalog" + else + echo "✗ Registry is not accessible from k3s host" + fi + echo "" + echo "Note: To push images, use:" + echo " export DOCKER_HOST=ssh://${LOCAL_K8S_HOST}" + echo " docker push localhost:30500/myimage:tag" + +# Deploy Docker registry manually +deploy-registry: + #!/bin/bash + set -euo pipefail + echo "Deploying local Docker registry..." + + kubectl apply -f ./registry/registry.yaml + + echo "Waiting for registry to be ready..." + kubectl wait --for=condition=available --timeout=60s deployment/registry -n registry + echo "✓ Registry deployed and ready" + +# Remove Docker registry +remove-registry: + #!/bin/bash + set -euo pipefail + if gum confirm "Remove local Docker registry?"; then + kubectl delete namespace registry --ignore-not-found + echo "✓ Registry removed" + else + echo "Registry removal cancelled." + fi + +# Configure k3s to use local registry +configure-registry: + #!/bin/bash + set -euo pipefail + echo "Configuring k3s registries.yaml..." + + ssh "${LOCAL_K8S_HOST}" "sudo mkdir -p /etc/rancher/k3s" + gomplate -f ./registry/registries.gomplate.yaml | ssh "${LOCAL_K8S_HOST}" "sudo tee /etc/rancher/k3s/registries.yaml > /dev/null" + + echo "Restarting k3s to apply registry configuration..." + ssh "${LOCAL_K8S_HOST}" "sudo systemctl restart k3s" + echo "✓ Registry configuration applied" diff --git a/k8s/registry/registries.gomplate.yaml b/k8s/registry/registries.gomplate.yaml new file mode 100644 index 0000000..3d70c5b --- /dev/null +++ b/k8s/registry/registries.gomplate.yaml @@ -0,0 +1,4 @@ +configs: + "localhost:30500": + tls: + insecure_skip_verify: true \ No newline at end of file diff --git a/k8s/registry/registry.yaml b/k8s/registry/registry.yaml new file mode 100644 index 0000000..f2a408b --- /dev/null +++ b/k8s/registry/registry.yaml @@ -0,0 +1,84 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: registry +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: registry + namespace: registry + labels: + app: registry +spec: + replicas: 1 + selector: + matchLabels: + app: registry + template: + metadata: + labels: + app: registry + spec: + containers: + - name: registry + image: registry:2 + ports: + - containerPort: 5000 + name: http + env: + - name: REGISTRY_STORAGE_DELETE_ENABLED + value: "true" + - name: REGISTRY_HTTP_ADDR + value: "0.0.0.0:5000" + volumeMounts: + - name: registry-data + mountPath: /var/lib/registry + livenessProbe: + httpGet: + path: /v2/ + port: 5000 + initialDelaySeconds: 30 + periodSeconds: 10 + readinessProbe: + httpGet: + path: /v2/ + port: 5000 + initialDelaySeconds: 5 + periodSeconds: 5 + volumes: + - name: registry-data + emptyDir: {} +--- +apiVersion: v1 +kind: Service +metadata: + name: registry + namespace: registry + labels: + app: registry +spec: + selector: + app: registry + ports: + - port: 5000 + targetPort: 5000 + name: http + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + name: registry-nodeport + namespace: registry + labels: + app: registry +spec: + selector: + app: registry + ports: + - port: 5000 + targetPort: 5000 + nodePort: 30500 + name: http + type: NodePort \ No newline at end of file