惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The Hacker News
The Hacker News
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
雷峰网
雷峰网
人人都是产品经理
人人都是产品经理
Recent Announcements
Recent Announcements
D
DataBreaches.Net
P
Proofpoint News Feed
V
Visual Studio Blog
J
Java Code Geeks
Recorded Future
Recorded Future
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
F
Full Disclosure
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
The GitHub Blog
The GitHub Blog
Engineering at Meta
Engineering at Meta
C
Cybersecurity and Infrastructure Security Agency CISA
V
Vulnerabilities – Threatpost
罗磊的独立博客
Jina AI
Jina AI
博客园 - 【当耐特】
C
CERT Recently Published Vulnerability Notes
G
GRAHAM CLULEY
Y
Y Combinator Blog
L
LangChain Blog
L
LINUX DO - 热门话题
宝玉的分享
宝玉的分享
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Help Net Security
云风的 BLOG
云风的 BLOG
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园_首页
A
About on SuperTechFans
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Latest news
Latest news
T
Threatpost
T
Tenable Blog
有赞技术团队
有赞技术团队
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Stack Overflow Blog
Stack Overflow Blog
C
Cisco Blogs
C
Check Point Blog
T
Tor Project blog
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
S
Schneier on Security
美团技术团队
I
Intezer
S
Securelist
AWS News Blog
AWS News Blog

Devoriales - DevOps and Python Tutorials

Cloud & DevOps & AI Digest: The Week of Jun 28, 2026 Cloud & DevOps & AI Digest: The Week of Jun 20, 2026 Ansible for DevOps Engineers: Architecture, Core Concepts, and Hands-On Lab Login Must-Have Kubernetes CLI Tools Every Platform Engineer Should Know Login Login Login Why Your Best Engineers Are Quitting (And How to Stop It) Login ArgoCD Vulnerability: How the ServerSideDiff Feature Exposes Kubernetes Secrets Login How Kubernetes Controls What Your Containers Can Do Login Multi-AZ Is Not Disaster Recovery: What the AWS Bahrain Outage Finally Proved Trivy Supply Chain Attack: When Your Security Scanner Becomes the Threat Is Claude Opus 4.6 Fast Mode Really Worth 6× the Price? Login Unlocking Higher Pod Density in EKS with Prefix Delegation AWS Regional NAT Gateway: What It Is and Why You Should Care Kubernetes 1.35 Timbernetes Release AWS re:Invent 2025: The Future of Kubernetes on EKS Debate Series: How Do We Control Deployment Order in Kubernetes? Debate Series: Should We Eliminate Kubernetes Secrets Entirely? Kubernetes CRDs Explained: A Beginner-Friendly Guide to Extending the Kubernetes API Reduce Cloud Cross-Zone Data Transfer Costs with Kubernetes 1.33 trafficDistribution Building Custom Bitnami Images: A Guide for Self-Hosted Container Images New Features in Kubernetes 1.34: An Overview From Free to Fee: How Broadcom's Bitnami Monetization Disrupts DevOps Infrastructure Claude Code Cheat Sheet: The Reference Guide Kubernetes Loses Enterprise Slack Status: Discord Among Platforms Being Considered Understanding Container Security: A Guide to Docker and Pod Security Container Patterns in Kubernetes: Init Containers, Sidecars, and Co-located Containers Explained AWS Launches Serverless MCP Server: AI-Powered Development Gets a Serverless Boost Valve Responds to Alleged Steam Data Breach Reports: What Users Need to Know ArgoCD 3.0: The Evolution Toward Secure GitOps Redis Returns to Open Source: The AGPLv3 Licensing Decision New Features in Kubernetes 1.33: An Overview Prometheus: How We Slashed Memory Usage IngressNightmare: Critical Ingress-NGINX Vulnerabilities and How to Check Your Exposure New Features in Kubernetes 1.32: An Overview What to Consider If You're Not Signing Up for Bitnami Premium Certified Kubernetes Administrator (CKA) Exam Updates for 2025 DeepSeek AI and the Question of the AI Bubble Python Tops the Tiobe Index: The Most Popular Programming Languages - January 2025 2024 in Review: IT Trends, Startups, and What’s Next Inside Argo: The Open-Source Journey Captured in a CNCF Documentary Running Docker on macOS Without Docker Desktop - updated with Kubernetes installation HashiCorp Rolls Out Terraform 2.0 at HashiConf, Keeps IBM Acquisition in the Shadows Is the EU Falling Behind in the Global AI Race? Prometheus Essentials: Node Exporter And System Monitoring Prometheus Essentials: Install and Start Monitoring Your App Prometheus Essentials: Introduction To Metric Types Kubernetes Pod Scheduling Explained: Taints, Tolerations, and Node Affinity Retrieval Augmented Generation (RAG) Explained for Beginners Like Me
Using Sealed Secrets with Your Kubernetes Applications
Aleksandro Matejic · 2024-06-23 · via Devoriales - DevOps and Python Tutorials

sealed secrets by bitnami

This blog post walks you through working with Sealed Secrets by Bitnami.

If you want to learn how to deploy the Sealed Secrets operator, please read the following blog post:

https://devoriales.com/post/350/deploy-sealed-secrets-operator-via-argocd-a-step-by-step-guide

Introduction

For those of us using GitOps principles in our solution, dealing with secrets can be a significant challenge. Since the single source of truth lies in the Git repository, we know that we cannot save secrets among the source code and manifest files.

sealed secrets commit secret

There are various solutions to this problem. More comprehensive options include using Secrets Managers like AWS Secrets Manager or HashiCorp Vault. However, for smaller projects and smaller teams, Sealed Secrets by Bitnami offers a simpler alternative.

commit sealed secret to git

It’s simpler because we don’t need to use any Secrets Managers. The way it works is we create a Sealed Secret manifest file using a public key certificate from the Sealed Secrets controller running in Kubernetes. Only the controller can decrypt the secret data once the Sealed Secret is applied to Kubernetes. You will store the Sealed Secret among your other manifest files, not the Kubernetes secret itself. Once deployed to Kubernetes, the Sealed Secrets controller will create a Kubernetes secret, which is then available to your workloads as usual.

There are several ways to expose secret data to a pod:

Environment Variables: Secrets can be injected into a container as environment variables.

Volume Mounts: Secrets can be mounted as files within a pod, making them accessible from the file system.

Kubernetes Downward API: Secrets can be made available to applications via the Kubernetes Downward API, allowing containers to consume secrets as part of the pod’s metadata.

For the sake of simplicity, in this tutorial, we’ll inject the secret data as environment variables.

Requirements

To follow along, you need to have the following:

  • A Kubernetes Cluster
  • An Container Image Registry
  • The Bitnami Sealed secrets controller running in your cluster
  • kubeseal cli tool to interact with the Sealed Secrets controller
  • ArgoCD (you can deploy the app without, this is not a hard requirement)

Install kubeseal cli

The kubeseal command-line interface (CLI) is a tool for managing Sealed Secrets in Kubernetes.

The kubeseal CLI allows you to encrypt your secrets into a SealedSecret, which can then be decrypted only by the Sealed Secrets controller running in your Kubernetes cluster.

I'd suggest that you install the kubeseal cli by following the official installation guide under the following link:

https://github.com/bitnami-labs/sealed-secrets?tab=readme-ov-file#kubeseal

The High Level Architecture

The following diagram shows how Sealed Secrets workflow looks like:

sealed secrets HLA

  1. Fetch Public Key Certificate: The developer retrieves the public key certificate from the Sealed Secrets controller. This certificate is necessary to encrypt secrets so that only the Sealed Secrets controller can decrypt them.
  2. The public-key-cert.pem:  gets created locally on developers machine.
  3. Create Kubernetes Secret Manifest: The developer creates a Kubernetes Secret manifest file containing the sensitive information to be encrypted. Using the kubeseal CLI and the fetched public key certificate, the developer encrypts the Kubernetes Secret.
  4. Encrypted Sealed Secret: The encrypted Sealed Secret manifest is saved to a file, ready to be committed to version control.
  5. Apply Sealed Secret Manifest: The Sealed Secret manifest gets applied to the Kubernetes cluster.
  6. Sealed Secret Applied: The Sealed Secret is now applied to the Kubernetes/Sealed Secrets Controller
  7. Kubernetes Secret Created: the Sealed Secrets controller creates a Kubernetes secret out of the sealed secret object.
  8. Applications use the Secret: Applications running in the Kubernetes cluster can now access and use the Kubernetes Secret.

The Project

We will deploy a dummy web app that will cosume some secret data.

All the code you can find in the following repository which can be fetched (or you can create an own repository and folder structure):

https://github.com/devoriales/sealed-secrets-example

The folder and file structure looks like the following:

.
├── README.md
├── app
│   ├── Dockerfile
│   ├── app.py
│   └── requirements.txt
├── k8s-manifests
│   ├── deployment.yaml
│   ├── ingress.yaml
│   └── service.yaml

We will deploy this application via ArgoCD, as we did with Sealed Secrets Controller in the previous blog post. But if you want to keep it simple, you can apply the manifest files manually.

Web App

The application will read data from a secret and use it as environment variables.

We will have two key value pairs:

  • USERNAME
  • PASSWORD

There is also an ingress, to be able to see the data in the browser. It may not make much sense for a real application, but it's just useful for demonstration purposes.

The application is based on flask and the code looks like this:

from flask import Flask
import os

app = Flask(__name__)

@app.route('/')
@app.route('/home')
def home():
    html = f'''
    <h1>Web App</h1>
    <p>Welcome to the home page</p>
    <p>Username: {os.environ.get('USERNAME')}</p>
    <p>Password: {os.environ.get('PASSWORD')}</p>
    '''
    return html

if __name__ == '__main__':
    app.run(debug=False, host='0.0.0.0', port=5050)

We're basically just getting the values from the environment variable that we will be exposed to the pod.

Build an image and push it to the registry

In the app folder, we have a Dockerfile to create a container image.

Go to the app folder and run:

docker build -t <my_registry>/web-app-sealed-secret:0.1.0 .

Be aware, you need to enter your own registry as part of the image tag.

You can of course name the image as you wish and comply with your registry.

Push the image to the registry

Next we need to push the image to the registry:

docker push -t <my_registry>/web-app-sealed-secret:0.1.0

Example:

docker push 192.168.64.54:30500/web-app-sealed-secret:0.1.0
The push refers to repository [192.168.64.54:30500/web-app-sealed-secret]
0c2e3ac1346a: Layer already exists 
3dfe04405ed5: Layer already exists 
bf25b5d627d8: Layer already exists 
fa3a4f5fdd2d: Layer already exists 
6f57bdc863f1: Layer already exists 
1bfa7d58f662: Layer already exists 
e76924ca5848: Layer already exists 
c015f78e2a88: Layer already exists 
a5290e2b0bfb: Layer already exists 
0.1.0: digest: sha256:ccf95b199b8e7129e33b33aca0840baa3debfa758dfd80571a955c603edea6a0 size: 2202

Great, now we have the image available in the registry.

Create the manifests files

In the k8s-manifests folder, there are already some manifests file.

The manifests files:

.
├── README.md
├── k8s-manifests
│   ├── deployment.yaml
│   ├── ingress.yaml
│   └── service.yaml

Deployment Manifest

Make sure to set the correct image name in your Deployment file:

spec:
  containers:
  - name: web-app
    image: 192.168.64.54:30500/web-app-sealed-secret:0.1.0

Ingress Manifest

You need to change the host name in the ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-app-ingress
  namespace: gitops-sealed-secret-demo
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: <set-your-hostname>
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-app-service
            port:
              number: 80

If you don't have the ingress controller in place, you can port forward to the service.

Create the Sealed Secret manifest

Finally we got to the point where we are going to create the Sealed Secret manifest file.

sealed secrets create manifest

The steps involve the following:

  1. Fetch the public key certificate from the Sealed Secrets Controller running in Kubernetes. For that we will use the kubeseal cli tool
  2. Create a Kubernetes secret manifest file locally keeping our secret data
  3. Encrypt the Kubernetes secret with kubeseal using the public key certificate. This will generate a Sealed Secret manifest file
  4. Add and commit the Sealed Secret manifest file among our other manifest file

Fetch the public key certificate

kubeseal cli is working under the kubectl context, as long as you have permissions to your kubernetes cluster, it will work.

To fetch the certificate, run the following command:

kubeseal --fetch-cert --controller-name=sealed-secrets --controller-namespace=sealed-secrets > public-key-cert.pem

–controller-name=sealed-secrets-controller:

• This option specifies the name of the Sealed Secrets controller. In most default installations, the controller is named sealed-secrets-controller.

After running the command, you should have a file named public-key-cert.pem in your current directory. This file contains the public certificate that kubeseal will use to encrypt your secrets.

Check that you have a valid public certificate by printing out the public-key-cert.pem file, it should show the public key:

-----BEGIN CERTIFICATE-----
JkIIEzDCCArSgAwIBAgIQb+VoA+cz7YJfXvk+NlRgvzANBgkqhkiG9w0BAQsFADAA
MB4XDTI0MDYyMTIwMzY1OVoXDTM0MDYxOTIwMzY1OVowADCCAiIwDQYJKoZIhvcN
AQEBBQADggIPADCCAgoCggIBAJ1vfKdoj+OLVcB4voW6V/Z/eHZIg4toZuJw9ORg
...
-----END CERTIFICATE-----

Create a Kubernetes secret

Next, we will create a Kubernetes secret. What's important here, this secret we will not commit to the git repository. Instead, we will create another manifest file called Sealed Secret.

Create a Kubernetes secret:

kubectl create secret generic mysecret --dry-run=client --from-literal=username=admin --from-literal=password='supersecretpassword' -o yaml > mysecret.yaml

Verify that you have a valid Kubernetes Secret:

cat my_secret.yaml     

Output example:

apiVersion: v1
data:
  password: c3VwZXJzZWNyZXRwYXNzd29yZA==
  username: YWRtaW4=
kind: Secret
metadata:
  creationTimestamp: null
  name: mysecret

Encrypt the Kubernetes secret with kubeseal

In this step, we are going to encrypt the secret that we have created with kubeseal. This will generate a Sealed Secret manifest file.

kubeseal -n sealed-secret-demo --cert public-key-cert.pem --format yaml < mysecret.yaml > sealedsecret.yaml

❗Please note, if you don’t specify the namespace using the -n option in the kubeseal command, the manifest file will contain the namespace configured in your kubectl context. So either you change the context or set the namespace flag.

What we are doing here is, when writing < mysecret.yaml, the command reads the input from the secret we created eariler.  

Verify that you have a sealed secret by printing out the sealedsecret.yaml file:

---
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  creationTimestamp: null
  name: mysecret
  namespace: gitops-sealed-secret-demo
spec:
  encryptedData:
    password: AgB0rhJWYqojdSVcn+49XQGnKkN+j79cza08goDBJrMd3dX7qTbgJJ+Klko929f7VUBv0LOP1gQBz/XJEMmLze4iqIHhz/w9ZDmxEOOjufTSYQy1/lztSMKb6qVt54Hj038iKbq43zIL3YgUZiF5aqqpj+F9CIoQKhsPACtM/VTN3sYHy1JwWyH6M/89uPjj/jPE9Khblm9iKIsx2BfqipR0K8fMOo9XtX+fUA4L8ORJBYKjN4yaGihnyTZV/3HKZd3gOsuL70GL7oPrBWLOh1ERVhh+dnoIv2RMPMJ94le53Fi8QWdBGI3zznPrf9fWDSwJa/76Zx3leqSTcBTwSftdcFTDpFEKd30qllav8lTMvr/jWsHKKrIZLFLZZ+tyBopHyCx3DrWoI39v9w1TilrVtL6+W4Uc/UAxdyHRLio9glWxANH+GjvLHHRrxsnGHtRqSEHNP2PeZ+EEhAKYSdOXURMWAbpIVbTiwd4NT6mD14plYx0Gxn+KLJkwhLFKhVUZPCjv+0SJhzHseW+xgNyoMHdq4bvYaICmSmmZLbMaqaPVeSWCElpiSzVCFLpYQleP6CDnnoQMRliNd84WAv9SjKRFQcuqM3NOp8gREBG05ucNKPk26UUF1+3+Xef2i9LEAkHtVDBumYjx07SUiCZ6usU2xxLaDttpOlp9xQdA/Mm9LXvCGS/N6a9pxE0Hwllo+geU/nJWgHU0LKV+9w==
    username: AgBaNDSRzBL/FqZUZXoGuttfOdecsB5Jqfiau7dJJFvqW4PLwV513Bhv9NLe59zavxg+dZe27HGszSZfbt0mDtiw4Usjk5icWnF9ZrZNAlim4cPJNslnYUxU8A5bTPsuQ9ZBJ88z2CEa7O6I08i5CpIyp6L6A2r2Y/S5Tz4YKyKbXzTAW8kBoOCsCqJ/5XsfKpgNBedP+xDYi+U3UxvET95RS/1HFPE8mTERdrqzTflNmduccgyJ34yuANFbi7YXO8UPE+4Ogcpw6LEPRKHNi4sajPbxCnAXZtiw9X30/DGF64V4RtB413U5m+3N9OrkQmK/Uq/YBsz7pr66C0JUyMAOeEdITfWEy8qtT5N4eG1PESr75zKz/n45kSXkkqbbv6WXCtFhKFd0Lrn9YHIfImgny93ZhyCjEnKRpGmno82Ut1PuykiPBCxnECORGn7+GxlWScdkRYt4Tv2c4ZctZUsSzP3Hrh1IIACMDw7smB879cXgXebKkEyZltPyyBMLN4gxcRw59Vk495LEvUAp4cteVwywPlx6mhPUX1gLMpqiXk5SXHT296C8m5sjNtGmzgx9ddDnmIzL4uL2ComtnxkENDupPyHk/FX4XFahN+FvaGZ+5hQh9eg91zN37reXY2uS8Ss019YIoFUjUBcPDA9FPpF9RoN/KzcQaZRV1PPl886ZJT6FnnjHFqdbMmSwXE5wsdu4uA==
  template:
    metadata:
      creationTimestamp: null
      name: mysecret
      namespace: gitops-sealed-secret-demo

You can safely add sealedsecret.yaml to your among your other manifest files. It can only be decrypted by the Sealed Secrets controller since it keeps the private key certificate.

Also make sure that your deployment manifest file refers to the correct secret name, which is mysecret in our case:

    spec:
      containers:
      - name: web-app
        image: 192.168.64.54:30500/web-app-sealed-secret:0.1.0
        env:
        - name: USERNAME
          valueFrom:
            secretKeyRef:
              name: mysecret
              key: username
        - name: PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysecret
              key: password
        ports:
        - containerPort: 5000

Commit and Deploy

You can add the new Sealed Secret file to your git repository:

git add k8s-manifests/sealed_secret.yaml
git commit -m "Add SealedSecret for application credentials"
git push origin <branch-name>

Now it's up to you how you want to deploy the app.

In my case, I'm running ArgoCD. If you do the same, you need to have an Application manifest file for the web-app.

ArgoCD application manifest example:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: gitops-secret-example
  namespace: argocd
spec:
  project: default
  source:
    repoURL: '[email protected]:devoriales/gitops-secret-example.git'
    path: k8s-manifests
    targetRevision: main
  destination:
    server: 'https://kubernetes.default.svc'
    namespace: gitops-sealed-secret-demo
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

If you don't have argoCD, you can apply the manifests files directly with kubectl:

kubectl apply -f k8s-manifests/

Output:

deployment.apps/web-app configured
ingress.networking.k8s.io/web-app-ingress configured
sealedsecret.bitnami.com/mysecret configured
service/web-app-service configured

Verify the web-app and secret key values

In this step, we will verify that our app is up and running.

In my case, since I’ve deployed the web app with ArgoCD, I can visually see that the application is healthy. It’s important to note that the Sealed Secrets controller created a Kubernetes secret from the SealedSecret, and we can see both objects.

Let’s go to the web browser and check if the secret data has been exposed to our application:

argoCD sealed secrets web app

Great! Our app is up and running and we got the password exposed to the whole world, exactly what we wanted 😂

Can I unseal a Sealed Secret?

Yes. But there is a bit of work.

Let's say you have installed Sealed Secrets operator in sealed-secrets namespace.

Then you need to get the private key from there.

Extract the private key (make sure you enter the correct secret name):

kubectl get secret sealed-secrets-keyv7jc7 -n sealed-secrets -o jsonpath="{.data.tls\.key}" | base64 --decode > sealed-secrets.key

sealed-secrets.key example:

-----BEGIN RSA PRIVATE KEY-----
MIIJKQIBAAKCAgEAnW98p2iP44tVwHi+hbpX9n94dkiDi2hm4nD05GA1wnSkPKYT
Qk+w6ob8MNecnm2VG8zw784IvBeEHP6jwmtbgDThY8OcpJ+zJJTi9fS/SQ3kQ4f5
...
-----END RSA PRIVATE KEY-----

Clone the Sealed Secrets repository and build the kubeseal tool with decryption capabilities:

git clone https://github.com/bitnami-labs/sealed-secrets.git
cd sealed-secrets
go build -tags decrypt ./cmd/kubeseal

Use the kubeseal cli with the private key to decrypt the Sealed Secret:

❗Please note It has to be the new kubeseal that you have built with the decryption capabilities:

./kubeseal --recovery-unseal --recovery-private-key sealed-secrets.key < sealedsecret.yaml > decrypted-secret.yaml

Open decrypted-secret.yaml to see the decrypted Kubernetes Secret:

{
  "kind": "Secret",
  "apiVersion": "v1",
  "metadata": {
    "name": "mysecret",
    "namespace": "sealed-secret-demo",
    "creationTimestamp": null,
    "ownerReferences": [
      {
        "apiVersion": "bitnami.com/v1alpha1",
        "kind": "SealedSecret",
        "name": "mysecret",
        "uid": "",
        "controller": true
      }
    ]
  },
  "data": {
    "password": "c3VwZXJzZWNyZXRwYXNzd29yZA==",
    "username": "YWRtaW4="
  }
}

And if we base64 decode the password, we see that it's correct:

c3VwZXJzZWNyZXRwYXNzd29yZA==

is

supersecretpassword

Wrapping Up

Sealed Secrets provides a solution for managing sensitive information in Kubernetes environments, particularly fitted well when following GitOps principles. By using Sealed Secrets controller, you can safely store the Sealed Secret manifest files in your Git repository without exposing the actual secret data.

This blog post guided you through the complete process, from setting up the necessary tools to deploying a sample web application using ArgoCD.

We covered:

  • Sealed Secrets Architecture on the high level
  • Fetching the public key certificate from the Sealed Secrets controller.
  • Creating and encrypting Kubernetes secrets.
  • Committing the SealedSecret manifests to your Git repository.
  • Deploying the application via ArgoCD.

As you implement this in your own projects, remember to keep your public key certificate secure and to review your deployment manifests to ensure they reference the correct SealedSecrets. Happy securing!