A simple Kubernetes client-go application that creates and patches imagePullSecrets to service accounts in all Kubernetes namespaces to allow cluster-wide authenticated access to private container registry.
This has been a very handy little application for us and I'd like at some point to add a simple chart so it simplifies the deployment for others.
I'm pasting here the Terraform module I created based on the example. The Helm chart should pretty much do exactly this under the hood but accept more configuration params:
locals {
imagepullsecrets_patcher_name = "imagepullsecrets-patcher"
imagepullsecrets_patcher_namespace = "kube-system"
}
resource "kubernetes_service_account" "image_pull_secrets" {
metadata {
name = local.imagepullsecrets_patcher_name
namespace = local.imagepullsecrets_patcher_namespace
}
}
resource "kubernetes_cluster_role" "image_pull_secrets" {
metadata {
name = local.imagepullsecrets_patcher_name
labels = {
k8s-app = local.imagepullsecrets_patcher_name
}
}
rule {
api_groups = [""]
resources = ["secrets", "serviceaccounts"]
verbs = ["list", "get", "patch", "create", "delete"]
}
rule {
api_groups = [""]
resources = ["namespaces"]
verbs = ["list", "get"]
}
}
resource "kubernetes_cluster_role_binding" "image_pull_secrets" {
metadata {
name = local.imagepullsecrets_patcher_name
}
role_ref {
api_group = "rbac.authorization.k8s.io"
kind = "ClusterRole"
name = kubernetes_cluster_role.image_pull_secrets.metadata[0].name
}
subject {
kind = "ServiceAccount"
name = kubernetes_service_account.image_pull_secrets.metadata[0].name
namespace = kubernetes_service_account.image_pull_secrets.metadata[0].namespace
}
}
resource "kubernetes_secret" "image_pull_secrets" {
metadata {
name = local.imagepullsecrets_patcher_name
namespace = local.imagepullsecrets_patcher_namespace
}
# We write a JSON file similar to what we have in ~/.docker/config.json to allow access to private registries
type = "kubernetes.io/dockerconfigjson"
data = {
".dockerconfigjson" = jsonencode({
"auths" : {
(var.url) : {
auth = var.auth_base64
}
}
})
}
}
resource "kubernetes_deployment" "image_pull_secrets" {
metadata {
name = local.imagepullsecrets_patcher_name
namespace = local.imagepullsecrets_patcher_namespace
labels = {
name = local.imagepullsecrets_patcher_name
}
}
spec {
replicas = 1
selector {
match_labels = {
name = local.imagepullsecrets_patcher_name
}
}
template {
metadata {
labels = {
name = local.imagepullsecrets_patcher_name
}
}
spec {
automount_service_account_token = true
service_account_name = kubernetes_service_account.image_pull_secrets.metadata[0].name
container {
name = "imagepullsecret-patcher"
image = "quay.io/titansoft/imagepullsecret-patcher:v0.14"
resources {
requests = {
cpu = "100m"
memory = "15Mi"
}
limits = {
cpu = "200m"
memory = "30Mi"
}
}
env {
name = "CONFIG_ALLSERVICEACCOUNT"
value = true
}
env {
name = "CONFIG_EXCLUDED_NAMESPACES"
value = join(",", var.excluded_namespaces)
}
env {
name = "CONFIG_LOOP_DURATION"
value = var.check_interval
}
env {
name = "CONFIG_SECRETNAME"
value = kubernetes_secret.image_pull_secrets.metadata[0].name
}
env {
name = "CONFIG_DOCKERCONFIGJSONPATH"
value = "/app/secrets/.dockerconfigjson"
}
volume_mount {
name = "src-dockerconfigjson"
mount_path = "/app/secrets"
read_only = true
}
}
volume {
name = "src-dockerconfigjson"
secret {
secret_name = kubernetes_secret.image_pull_secrets.metadata[0].name
}
}
}
}
}
}
variable "url" {
description = "The URL of the private registry. Can be provided as a full URL or just the domain name (e.g. docker.pkg.github.com)."
type = string
}
variable "auth_base64" {
description = "The base64-encoded auth credentials for the registry. Usually in the decoded form or `username:password`."
type = string
}
variable "check_interval" {
description = "The interval to periodically check for new service accounts to patch"
type = string
default = "30s"
}
variable "excluded_namespaces" {
description = "List of namespaces to exclude from patching their service accounts with the private registry configuration"
type = list(string)
default = [
"kube-node-lease",
"kube-public",
"kube-system",
]
}
This has been a very handy little application for us and I'd like at some point to add a simple chart so it simplifies the deployment for others.
I'm pasting here the Terraform module I created based on the example. The Helm chart should pretty much do exactly this under the hood but accept more configuration params: