Exploring Secrets and ConfigMaps in Kubernetes
When working with Kubernetes, one of the common tasks is to deploy containers from private Docker registries. To securely manage access to these registries, Kubernetes uses Secrets. In this blog post, we’ll walk through how to create a Docker registry secret and use it to pull images in a Kubernetes deployment.
Step 1: Creating a Docker Registry Secret
To securely store your Docker credentials, we use Kubernetes Secrets. This is how you create a secret for Docker registry credentials:
kubectl create secret docker-registry docker-pwd \
--docker-username="<your-username>" \
--docker-password="<your-password>" \
--docker-email="<your-email>"
Step 2: Referencing the Secret in Your Kubernetes Deployment
Now that the secret is created, you can use it in your Kubernetes Deployment to allow Kubernetes to pull the private Docker image. Here’s a simple Deployment YAML file:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: aws-cli
name: aws-cli
spec:
replicas: 3
selector:
matchLabels:
app: aws-cli
template:
metadata:
labels:
app: aws-cli
spec:
containers:
- image: suryaprasad9773/troubleshootingtools:v1
name: configsecrets
imagePullSecrets:
- name: docker-pwd
By using imagePullSecrets, Kubernetes can securely authenticate and pull images from a private registry. Storing credentials in Kubernetes secrets ensures sensitive data like Docker passwords are never exposed in plain text. This method is essential for running applications that rely on private images in Kubernetes, ensuring both security and ease of management.
Managing Generic Secrets in Kubernetes:
In Kubernetes, Generic Secrets help you securely store sensitive information like passwords, API keys, or credentials. These secrets can then be used in your applications without exposing them in your code or configuration files.
Creating Generic Secrets
- Create a secret for a username and password:
kubectl create secret generic db-user --from-literal=username=admin
kubectl create secret generic db-pass --from-literal=password='mysecretpassword'
This stores the username and password securely in your Kubernetes cluster.
Viewing Secrets:
kubectl get secrets
Decoding Secrets:
kubectl get secret db-user -o jsonpath="{.data.username}" | base64 --decode
kubectl get secret db-pass -o jsonpath="{.data.password}" | base64 --decode
Base64 Encoding Secrets:
If you need to manually encode data for a secret, you can use the Base64 command:
Encode a value:
echo -n "mysecretvalue" | base64
Decode a value:
echo "bXlzZWNyZXR2YWx1ZQ==" | base64 --decode
Creating the Secret:
apiVersion: v1
kind: Secret
metadata:
name: aws-credentials
data:
AWS_ACCESS_KEY_ID: <base64-encoded-access-key-id>
AWS_SECRET_ACCESS_KEY: <base64-encoded-secret-access-key>
- Secret: This object stores the AWS Access Key ID and Secret Access Key.
- data: The sensitive values like
AWS_ACCESS_KEY_ID
andAWS_SECRET_ACCESS_KEY
are stored in Base64 encoded format. - You must encode the Access Key ID and Secret Access Key into Base64 before placing them here.
To encode the values into Base64:
- Run
echo -n 'your-access-key-id' | base64
to get the encoded access key. - Run
echo -n 'your-secret-access-key' | base64
to get the encoded secret key.
Creating the Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: aws-cli
name: awscli-deployment
spec:
replicas: 3
selector:
matchLabels:
app: aws-cli
template:
metadata:
labels:
app: aws-cli
spec:
containers:
- image: suryaprasad9773/troubleshootingtools:v1
name: aws-cli
env:
- name: AWS_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: aws-credentials
key: AWS_ACCESS_KEY_ID
- name: AWS_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: aws-credentials
key: AWS_SECRET_ACCESS_KEY
- name: AWS_REGION
value: "us-east-1"
Steps:
kubectl apply -f secret.yaml
kubectl apply -f deployment.yaml
kubectl get pods
kubectl exec -it <pod-name> -- aws s3 ls
Generic Secrets in Kubernetes help you securely manage sensitive information like usernames and passwords. By creating secrets, decoding them when necessary, and using them in your deployments, you can protect your application’s credentials while keeping your environment secure.
ConfigMaps:
Step 1: Create a Custom Nginx Configuration
We want to configure Nginx with custom settings. Instead of modifying the default configuration inside the container, we use ConfigMaps to provide our custom Nginx configuration file (nginx.conf).
worker_processes 1;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
server {
listen 9999;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
}
This configuration does the following:
- It configures Nginx to listen on port
9999
. - It includes logging, file transfer, and other Nginx settings.
- It specifies the root directory and index files for serving static content.
Step 2. Create a ConfigMap with Nginx Configuration
kubectl create configmap nginx-config --from-file=nginx.conf
Step 3: Create the Deployment for Nginx
Now, let’s create the Deployment YAML file for Nginx. This deployment will run one replica of the Nginx container and mount the custom nginx.conf file from the ConfigMap.
Here’s the Deployment YAML:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
volumeMounts:
- name: nginx-config-volume
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf # Ensure the config file is placed at the correct path
ports:
- containerPort: 9999
volumes:
- name: nginx-config-volume
configMap:
name: nginx-config
Step 4: Expose the Nginx Deployment with a Service
To allow traffic to reach our Nginx container, we expose it via a Service. In this case, we are using a NodePort service, which makes the application accessible externally via a port on the Kubernetes node.
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 9999
type: NodePort
Step 5: Deploy Everything to Kubernetes
Now that we have our YAML files for the ConfigMap, Deployment, and Service, let’s apply them to the Kubernetes cluster.
kubectl apply -f nginx-deployment.yaml
kubectl apply -f nginx-service.yaml
kubectl get svc nginx-service
this will give you an external port under the nodeport range. you can access the nginx server by using the node’s ip address and the exposed port, e.g., http://<node-ip>:<nodeport>.com