{"id":2161,"date":"2025-11-23T04:38:23","date_gmt":"2025-11-23T04:38:23","guid":{"rendered":"https:\/\/www.nicktailor.com\/?p=2161"},"modified":"2025-11-23T05:02:21","modified_gmt":"2025-11-23T05:02:21","slug":"how-to-deploy-a-kubernetes-application-with-a-clean-namespace-structure","status":"publish","type":"post","link":"https:\/\/nicktailor.com\/tech-blog\/how-to-deploy-a-kubernetes-application-with-a-clean-namespace-structure\/","title":{"rendered":"How to Deploy a Kubernetes Application with a Clean Namespace Structure"},"content":{"rendered":"<h1>How to Deploy a Kubernetes Application with a Clean Namespace Structure<\/h1>\n<p>When you deploy an application to Kubernetes in production, you shouldn\u2019t throw everything into the <code>default<\/code> namespace or a single giant YAML file. A proper setup uses:<\/p>\n<ul>\n<li>A dedicated <strong>namespace<\/strong> for the app<\/li>\n<li>A <strong>ServiceAccount<\/strong> and <strong>RBAC<\/strong> for security<\/li>\n<li><strong>ConfigMap<\/strong> and <strong>Secret<\/strong> for configuration<\/li>\n<li><strong>Deployment<\/strong>, <strong>Service<\/strong>, and <strong>Ingress<\/strong> for runtime and traffic<\/li>\n<li><strong>HPA<\/strong>, <strong>PDB<\/strong>, and <strong>NetworkPolicies<\/strong> for reliability and security<br \/>\n<h1 data-start=\"2177\" data-end=\"2203\"><strong data-start=\"2179\" data-end=\"2203\">HPA vs PDB (Summary)<\/strong><\/h1>\n<h1 data-start=\"2204\" data-end=\"2230\">========================<\/h1>\n<div class=\"_tableContainer_1rjym_1\">\n<div class=\"group _tableWrapper_1rjym_13 flex w-fit flex-col-reverse\" tabindex=\"-1\">\n<table class=\"w-fit min-w-(--thread-content-width)\" data-start=\"2232\" data-end=\"2651\">\n<thead data-start=\"2232\" data-end=\"2255\">\n<tr data-start=\"2232\" data-end=\"2255\">\n<th data-start=\"2232\" data-end=\"2242\" data-col-size=\"sm\">Feature<\/th>\n<th data-start=\"2242\" data-end=\"2248\" data-col-size=\"sm\">HPA<\/th>\n<th data-start=\"2248\" data-end=\"2255\" data-col-size=\"sm\">PDB<\/th>\n<\/tr>\n<\/thead>\n<tbody data-start=\"2279\" data-end=\"2651\">\n<tr data-start=\"2279\" data-end=\"2323\">\n<td data-start=\"2279\" data-end=\"2307\" data-col-size=\"sm\">Scales pods based on load<\/td>\n<td data-col-size=\"sm\" data-start=\"2307\" data-end=\"2315\">\u2714 YES<\/td>\n<td data-col-size=\"sm\" data-start=\"2315\" data-end=\"2323\">\u274c NO<\/td>\n<\/tr>\n<tr data-start=\"2324\" data-end=\"2371\">\n<td data-start=\"2324\" data-end=\"2355\" data-col-size=\"sm\">Ensures minimum pods stay up<\/td>\n<td data-col-size=\"sm\" data-start=\"2355\" data-end=\"2362\">\u274c NO<\/td>\n<td data-col-size=\"sm\" data-start=\"2362\" data-end=\"2371\">\u2714 YES<\/td>\n<\/tr>\n<tr data-start=\"2372\" data-end=\"2416\">\n<td data-start=\"2372\" data-end=\"2400\" data-col-size=\"sm\">Helps with traffic spikes<\/td>\n<td data-col-size=\"sm\" data-start=\"2400\" data-end=\"2408\">\u2714 YES<\/td>\n<td data-col-size=\"sm\" data-start=\"2408\" data-end=\"2416\">\u274c NO<\/td>\n<\/tr>\n<tr data-start=\"2417\" data-end=\"2467\">\n<td data-start=\"2417\" data-end=\"2451\" data-col-size=\"sm\">Protects during upgrades\/drains<\/td>\n<td data-col-size=\"sm\" data-start=\"2451\" data-end=\"2458\">\u274c NO<\/td>\n<td data-col-size=\"sm\" data-start=\"2458\" data-end=\"2467\">\u2714 YES<\/td>\n<\/tr>\n<tr data-start=\"2468\" data-end=\"2517\">\n<td data-start=\"2468\" data-end=\"2501\" data-col-size=\"sm\">Operates on load (CPU\/metrics)<\/td>\n<td data-col-size=\"sm\" data-start=\"2501\" data-end=\"2509\">\u2714 YES<\/td>\n<td data-col-size=\"sm\" data-start=\"2509\" data-end=\"2517\">\u274c NO<\/td>\n<\/tr>\n<tr data-start=\"2518\" data-end=\"2560\">\n<td data-start=\"2518\" data-end=\"2544\" data-col-size=\"sm\">Operates on disruptions<\/td>\n<td data-col-size=\"sm\" data-start=\"2544\" data-end=\"2551\">\u274c NO<\/td>\n<td data-col-size=\"sm\" data-start=\"2551\" data-end=\"2560\">\u2714 YES<\/td>\n<\/tr>\n<tr data-start=\"2561\" data-end=\"2605\">\n<td data-start=\"2561\" data-end=\"2589\" data-col-size=\"sm\">Controls min\/max replicas<\/td>\n<td data-col-size=\"sm\" data-start=\"2589\" data-end=\"2597\">\u2714 YES<\/td>\n<td data-col-size=\"sm\" data-start=\"2597\" data-end=\"2605\">\u274c NO<\/td>\n<\/tr>\n<tr data-start=\"2606\" data-end=\"2651\">\n<td data-start=\"2606\" data-end=\"2635\" data-col-size=\"sm\">Controls disruption limits<\/td>\n<td data-col-size=\"sm\" data-start=\"2635\" data-end=\"2642\">\u274c NO<\/td>\n<td data-col-size=\"sm\" data-start=\"2642\" data-end=\"2651\">\u2714 YES<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<\/li>\n<\/ul>\n<p>In this post, we\u2019ll walk through a clean, real-world Kubernetes namespace structure, show the YAML for each section, and explain what it does. You can drop all of these files into a directory and apply them in one go with:<\/p>\n<pre><code>kubectl apply -f k8s\/\n<\/code><\/pre>\n<hr \/>\n<h2>1. Directory Structure<\/h2>\n<p>Create a folder for your Kubernetes manifests, for example:<\/p>\n<pre><code>k8s\/\n  namespace.yaml\n  serviceaccount.yaml\n  rbac.yaml\n  configmap.yaml\n  secret.yaml\n  deployment.yaml\n  service.yaml\n  ingress.yaml\n  hpa.yaml\n  pdb.yaml\n  networkpolicy-default-deny.yaml\n  networkpolicy-allow-ingress.yaml\n<\/code><\/pre>\n<p>Kubernetes will treat all of these files as one desired state when you run <code>kubectl apply -f k8s\/<\/code>, similar to how Terraform reads multiple <code>.tf<\/code> files in one directory.<\/p>\n<hr \/>\n<h2>2. Namespace \u2013 Isolating the Application<\/h2>\n<p>A namespace is a logical boundary in the cluster. Think of it as a dedicated \u201cfolder\u201d for your application\u2019s resources.<\/p>\n<pre><code class=\"language-yaml\">apiVersion: v1\nkind: Namespace\nmetadata:\n  name: prod-app\n  labels:\n    name: prod-app\n    pod-security.kubernetes.io\/enforce: \"restricted\"\n    pod-security.kubernetes.io\/enforce-version: \"latest\"\n<\/code><\/pre>\n<p><strong>What this does:<\/strong><\/p>\n<ul>\n<li>Creates a namespace called <code>prod-app<\/code>.<\/li>\n<li>Applies Pod Security labels to enforce restricted policies.<\/li>\n<li>Gives you a clean way to separate dev, staging, and prod environments.<\/li>\n<\/ul>\n<hr \/>\n<h2>3. ServiceAccount \u2013 Identity for the Pods<\/h2>\n<p>A <code>ServiceAccount<\/code> represents the identity your pods use inside Kubernetes. Instead of relying on the default ServiceAccount, you create a dedicated one for your app.<\/p>\n<pre><code class=\"language-yaml\">apiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: app-sa\n  namespace: prod-app\n<\/code><\/pre>\n<p><strong>What this does:<\/strong><\/p>\n<ul>\n<li>Creates a ServiceAccount named <code>app-sa<\/code> in the <code>prod-app<\/code> namespace.<\/li>\n<li>Your Deployment will run pods using this identity, not the insecure default.<\/li>\n<\/ul>\n<hr \/>\n<h2>4. RBAC \u2013 Roles and RoleBindings<\/h2>\n<p>RBAC (Role-Based Access Control) defines what your application is allowed to do inside the namespace. You don\u2019t want your app to have full cluster access; you give it just enough permissions.<\/p>\n<pre><code class=\"language-yaml\">apiVersion: rbac.authorization.k8s.io\/v1\nkind: Role\nmetadata:\n  name: app-read-config\n  namespace: prod-app\nrules:\n  - apiGroups: [\"\"]\n    resources: [\"configmaps\", \"secrets\"]\n    verbs: [\"get\", \"list\"]\n\n---\napiVersion: rbac.authorization.k8s.io\/v1\nkind: RoleBinding\nmetadata:\n  name: app-read-config-binding\n  namespace: prod-app\nsubjects:\n  - kind: ServiceAccount\n    name: app-sa\n    namespace: prod-app\nroleRef:\n  kind: Role\n  name: app-read-config\n  apiGroup: rbac.authorization.k8s.io\n<\/code><\/pre>\n<p><strong>What this does:<\/strong><\/p>\n<ul>\n<li><code>Role<\/code> <code>app-read-config<\/code>:\n<ul>\n<li>Allows reading (<code>get<\/code>, <code>list<\/code>) ConfigMaps and Secrets in this namespace.<\/li>\n<\/ul>\n<\/li>\n<li><code>RoleBinding<\/code>:\n<ul>\n<li>Attaches that Role to the <code>app-sa<\/code> ServiceAccount.<\/li>\n<li>Any pod running as <code>app-sa<\/code> can now read ConfigMaps and Secrets in <code>prod-app<\/code>.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<hr \/>\n<h2>5. ConfigMap \u2013 Non-Sensitive Configuration<\/h2>\n<p>A ConfigMap holds non-secret configuration such as runtime flags, modes, switches, or log levels.<\/p>\n<pre><code class=\"language-yaml\">apiVersion: v1\nkind: ConfigMap\nmetadata:\n  name: app-config\n  namespace: prod-app\ndata:\n  APP_ENV: \"production\"\n  APP_LOG_LEVEL: \"info\"\n<\/code><\/pre>\n<p><strong>What this does:<\/strong><\/p>\n<ul>\n<li>Stores plain-text configuration for your application.<\/li>\n<li>Lets you change behavior without rebuilding the container image.<\/li>\n<\/ul>\n<hr \/>\n<h2>6. Secret \u2013 Sensitive Configuration<\/h2>\n<p>Secrets hold confidential settings such as database URLs, API keys, and credentials.<\/p>\n<pre><code class=\"language-yaml\">apiVersion: v1\nkind: Secret\nmetadata:\n  name: app-secret\n  namespace: prod-app\ntype: Opaque\nstringData:\n  DATABASE_URL: \"postgres:\/\/user:password@db.prod:5432\/app\"\n  API_KEY_EXTERNAL_SERVICE: \"replace-me\"\n<\/code><\/pre>\n<p><strong>What this does:<\/strong><\/p>\n<ul>\n<li>Stores sensitive data separately from code.<\/li>\n<li>Works with RBAC so only the right ServiceAccount can read it.<\/li>\n<\/ul>\n<hr \/>\n<h2>7. Deployment \u2013 The Application Workload<\/h2>\n<p>The Deployment defines how your containers run: image, replicas, health checks, resources, and security context. This is the core of your application\u2019s runtime behavior.<\/p>\n<pre><code class=\"language-yaml\">apiVersion: apps\/v1\nkind: Deployment\nmetadata:\n  name: app-deployment\n  namespace: prod-app\n  labels:\n    app: my-app\nspec:\n  replicas: 3\n  revisionHistoryLimit: 5\n  strategy:\n    type: RollingUpdate\n    rollingUpdate:\n      maxUnavailable: 0\n      maxSurge: 1\n  selector:\n    matchLabels:\n      app: my-app\n  template:\n    metadata:\n      labels:\n        app: my-app\n    spec:\n      serviceAccountName: app-sa\n      automountServiceAccountToken: false\n      securityContext:\n        runAsNonRoot: true\n        runAsUser: 1000\n        runAsGroup: 1000\n        fsGroup: 1000\n      containers:\n        - name: app\n          image: your-registry\/your-image:TAG\n          imagePullPolicy: IfNotPresent\n          ports:\n            - containerPort: 8080\n              name: http\n          envFrom:\n            - configMapRef:\n                name: app-config\n            - secretRef:\n                name: app-secret\n          resources:\n            requests:\n              cpu: \"200m\"\n              memory: \"256Mi\"\n            limits:\n              cpu: \"500m\"\n              memory: \"512Mi\"\n          readinessProbe:\n            httpGet:\n              path: \/healthz\n              port: http\n            initialDelaySeconds: 5\n            periodSeconds: 10\n          livenessProbe:\n            httpGet:\n              path: \/livez\n              port: http\n            initialDelaySeconds: 15\n            periodSeconds: 20\n          securityContext:\n            readOnlyRootFilesystem: true\n            allowPrivilegeEscalation: false\n            capabilities:\n              drop:\n                - ALL\n      terminationGracePeriodSeconds: 30\n<\/code><\/pre>\n<p><strong>What this does:<\/strong><\/p>\n<ul>\n<li>Runs 3 replicas of your application for availability.<\/li>\n<li>Uses a safe rolling update strategy with zero downtime (<code>maxUnavailable: 0<\/code>, <code>maxSurge: 1<\/code>).<\/li>\n<li>Runs pods under the <code>app-sa<\/code> ServiceAccount, inheriting its RBAC permissions.<\/li>\n<li>Injects configuration from <code>ConfigMap<\/code> and <code>Secret<\/code>.<\/li>\n<li>Defines health checks (<code>readinessProbe<\/code>, <code>livenessProbe<\/code>) so Kubernetes knows when to route traffic and when to restart pods.<\/li>\n<li>Applies strict security settings (non-root user, no privilege escalation, read-only root filesystem).<\/li>\n<\/ul>\n<hr \/>\n<h2>8. Service \u2013 Internal Load Balancer<\/h2>\n<p>A Service provides a stable, cluster-internal endpoint to reach your pods.<\/p>\n<pre><code class=\"language-yaml\">apiVersion: v1\nkind: Service\nmetadata:\n  name: app-service\n  namespace: prod-app\n  labels:\n    app: my-app\nspec:\n  type: ClusterIP\n  selector:\n    app: my-app\n  ports:\n    - name: http\n      port: 80\n      targetPort: http\n<\/code><\/pre>\n<p><strong>What this does:<\/strong><\/p>\n<ul>\n<li>Maps port 80 on the Service to port 8080 on the pods (via the named port <code>http<\/code>).<\/li>\n<li>Provides stable DNS: <code>app-service.prod-app.svc.cluster.local<\/code>.<\/li>\n<li>Load balances traffic across all healthy pods with <code>app: my-app<\/code>.<\/li>\n<\/ul>\n<hr \/>\n<h2>9. Ingress \u2013 External HTTP\/HTTPS Access<\/h2>\n<p>Ingress exposes your Service to the outside world using a hostname and optional TLS.<\/p>\n<pre><code class=\"language-yaml\">apiVersion: networking.k8s.io\/v1\nkind: Ingress\nmetadata:\n  name: app-ingress\n  namespace: prod-app\n  annotations:\n    kubernetes.io\/ingress.class: \"nginx\"\n    nginx.ingress.kubernetes.io\/ssl-redirect: \"true\"\nspec:\n  tls:\n    - hosts:\n        - app.your-domain.com\n      secretName: app-tls-secret\n  rules:\n    - host: app.your-domain.com\n      http:\n        paths:\n          - path: \/\n            pathType: Prefix\n            backend:\n              service:\n                name: app-service\n                port:\n                  number: 80\n<\/code><\/pre>\n<p><strong>What this does:<\/strong><\/p>\n<ul>\n<li>Routes traffic from <code>https:\/\/app.your-domain.com<\/code> to <code>app-service<\/code> on port 80.<\/li>\n<li>Uses <code>app-tls-secret<\/code> for TLS termination (usually created by cert-manager).<\/li>\n<li>Relies on an Ingress controller (e.g., NGINX) running in the cluster.<\/li>\n<\/ul>\n<hr \/>\n<h2>10. Horizontal Pod Autoscaler (HPA) \u2013 Scaling on Load<\/h2>\n<p>The HPA automatically adjusts the number of replicas based on metrics like CPU usage.<\/p>\n<pre><code class=\"language-yaml\">apiVersion: autoscaling\/v2\nkind: HorizontalPodAutoscaler\nmetadata:\n  name: app-hpa\n  namespace: prod-app\nspec:\n  scaleTargetRef:\n    apiVersion: apps\/v1\n    kind: Deployment\n    name: app-deployment\n  minReplicas: 3\n  maxReplicas: 10\n  metrics:\n    - type: Resource\n      resource:\n        name: cpu\n        target:\n          type: Utilization\n          averageUtilization: 60\n<\/code><\/pre>\n<p><strong>What this does:<\/strong><\/p>\n<ul>\n<li>Keeps at least 3 pods running, and can scale up to 10.<\/li>\n<li>Targets the <code>app-deployment<\/code> Deployment.<\/li>\n<li>Scales based on CPU usage (e.g., above 60% average).<\/li>\n<\/ul>\n<hr \/>\n<h2>11. PodDisruptionBudget (PDB) \u2013 Protecting Availability<\/h2>\n<p>A PodDisruptionBudget ensures that voluntary disruptions (node drains, upgrades) don\u2019t take down too many pods at once.<\/p>\n<pre><code class=\"language-yaml\">apiVersion: policy\/v1\nkind: PodDisruptionBudget\nmetadata:\n  name: app-pdb\n  namespace: prod-app\nspec:\n  minAvailable: 2\n  selector:\n    matchLabels:\n      app: my-app\n<\/code><\/pre>\n<p><strong>What this does:<\/strong><\/p>\n<ul>\n<li>Guarantees that at least 2 pods are always available.<\/li>\n<li>Protects your app during maintenance and cluster upgrades.<\/li>\n<\/ul>\n<hr \/>\n<h2>12. Network Policies \u2013 Zero-Trust Networking<\/h2>\n<p>By default, Kubernetes allows every pod to talk to every other pod. NetworkPolicies let you move to a zero-trust model.<\/p>\n<h3>Default Deny Policy<\/h3>\n<pre><code class=\"language-yaml\">apiVersion: networking.k8s.io\/v1\nkind: NetworkPolicy\nmetadata:\n  name: default-deny-all\n  namespace: prod-app\nspec:\n  podSelector: {}\n  policyTypes:\n    - Ingress\n    - Egress\n<\/code><\/pre>\n<p><strong>What this does:<\/strong><\/p>\n<ul>\n<li>Blocks all ingress and egress traffic for all pods in the namespace, unless explicitly allowed.<\/li>\n<\/ul>\n<h3>Allow Traffic from Ingress Controller to the App<\/h3>\n<pre><code class=\"language-yaml\">apiVersion: networking.k8s.io\/v1\nkind: NetworkPolicy\nmetadata:\n  name: allow-from-ingress\n  namespace: prod-app\nspec:\n  podSelector:\n    matchLabels:\n      app: my-app\n  policyTypes:\n    - Ingress\n    - Egress\n  ingress:\n    - from:\n        - namespaceSelector:\n            matchLabels:\n              app.kubernetes.io\/name: ingress-nginx\n      ports:\n        - protocol: TCP\n          port: 80\n  egress:\n    - to:\n        - namespaceSelector: {}\n      ports:\n        - protocol: TCP\n          port: 5432\n        - protocol: TCP\n          port: 443\n<\/code><\/pre>\n<p><strong>What this does:<\/strong><\/p>\n<ul>\n<li>Allows only the Ingress controller namespace (e.g. <code>ingress-nginx<\/code>) to send HTTP traffic to the app.<\/li>\n<li>Restricts egress traffic to specific ports (e.g., PostgreSQL and HTTPS).<\/li>\n<\/ul>\n<hr \/>\n<h2>Applying Everything<\/h2>\n<p>Once you have all these files in your <code>k8s\/<\/code> directory, you deploy the entire application stack with:<\/p>\n<pre><code>kubectl apply -f k8s\/\n<\/code><\/pre>\n<p>Kubernetes reads all files, builds the state internally, and creates or updates resources in the correct order, very similar to how Terraform applies all <code>.tf<\/code> files in a directory.<\/p>\n<hr \/>\n<h2>Conclusion<\/h2>\n<p>A production-ready Kubernetes deployment is not just a Deployment and a Service. It is a structured set of manifests that cover identity, security, configuration, scaling, networking, and reliability.<\/p>\n<ul>\n<li><strong>Namespace<\/strong> \u2013 isolates your application.<\/li>\n<li><strong>ServiceAccount + RBAC<\/strong> \u2013 define identity and permissions.<\/li>\n<li><strong>ConfigMap + Secret<\/strong> \u2013 handle configuration and sensitive data.<\/li>\n<li><strong>Deployment + Service + Ingress<\/strong> \u2013 run the app and expose it.<\/li>\n<li><strong>HPA + PDB<\/strong> \u2013 keep it scalable and resilient.<\/li>\n<li><strong>NetworkPolicies<\/strong> \u2013 secure communication with a zero-trust model.<\/li>\n<\/ul>\n<p>With this structure in place, you have a clean, repeatable Kubernetes deployment that fits naturally into Git, CI\/CD, and GitOps workflows.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>How to Deploy a Kubernetes Application with a Clean Namespace Structure When you deploy an application to Kubernetes in production, you shouldn\u2019t throw everything into the default namespace or a single giant YAML file. A proper setup uses: A dedicated namespace for the app A ServiceAccount and RBAC for security ConfigMap and Secret for configuration Deployment, Service, and Ingress for<a href=\"https:\/\/nicktailor.com\/tech-blog\/how-to-deploy-a-kubernetes-application-with-a-clean-namespace-structure\/\" class=\"read-more\">Read More &#8230;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[148],"tags":[],"class_list":["post-2161","post","type-post","status-publish","format-standard","hentry","category-kubernetes"],"_links":{"self":[{"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/posts\/2161","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/comments?post=2161"}],"version-history":[{"count":2,"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/posts\/2161\/revisions"}],"predecessor-version":[{"id":2163,"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/posts\/2161\/revisions\/2163"}],"wp:attachment":[{"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/media?parent=2161"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/categories?post=2161"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nicktailor.com\/tech-blog\/wp-json\/wp\/v2\/tags?post=2161"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}