<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged mdm</title>
<link>https://coderlegion.com/tag/mdm</link>
<description>Powered by Question2Answer</description>
<item>
<title>DNS: The phonebook of the internet.</title>
<link>https://coderlegion.com/11450/dns-the-phonebook-of-the-internet</link>
<description>&lt;p&gt;One‑line: DNS = the phonebook of the internet.&lt;/p&gt;
&lt;p&gt;Two‑words: Name‑resolution.&lt;/p&gt;
&lt;p&gt;Business analogy: Instead of memorizing everyone’s phone number, you look up their name in a directory — DNS is that directory for computers.&lt;/p&gt;
&lt;p&gt;Mechanical definition (tight, clean)&lt;br&gt;
DNS (Domain Name System) converts human‑friendly names into machine‑friendly IP addresses.&lt;/p&gt;
&lt;p&gt;Examples:&lt;/p&gt;
&lt;p&gt;google.com → 142.250.72.14&lt;br&gt;
kafka.svc.cluster.local → the pod’s internal cluster IP&lt;br&gt;
elasticsearch.default.svc.cluster.local → the StatefulSet’s service IP&lt;/p&gt;
&lt;h3 id=&quot;you-type-the-name-dns-returns-the-ip-your-app-connects-&quot;&gt;You type the name → DNS returns the IP → your app connects.&lt;/h3&gt;
&lt;p&gt;Why it matters for Docker vs Kubernetes&lt;/p&gt;
&lt;h2 id=&quot;docker-single-host-&quot;&gt;Docker (single host)&lt;/h2&gt;
&lt;p&gt;Containers can cheat and use localhost&lt;br&gt;
DNS barely matters because everything shares one machine&lt;/p&gt;
&lt;h2 id=&quot;kubernetes-multi-node-&quot;&gt;Kubernetes (multi‑node)&lt;/h2&gt;
&lt;p&gt;Pods move&lt;br&gt;
IPs change&lt;br&gt;
Nodes change&lt;br&gt;
Restarts happen&lt;/p&gt;
&lt;p&gt;So the only stable way to reach anything is through DNS names, not IPs or localhost.&lt;/p&gt;
&lt;p&gt;Examples:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;kafka:9092
zookeeper:2181
elasticsearch:9200
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;or in full cluster form:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;kafka.svc.cluster.local:9092
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The rule for distributed systems&lt;br&gt;
If you can’t reach it by DNS, you don’t have a real distributed system yet.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;One‑line: Here are the exact DNS names and the Docker‑side simulation.&lt;/p&gt;
&lt;p&gt;Two‑words: Cluster realism.&lt;/p&gt;
&lt;p&gt;Business analogy: Teach your app to use street addresses (DNS) even when it’s still living in your garage (Docker).&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Exact DNS Names for Kafka / ELK / MDM in Kubernetes&lt;br&gt;
These are the canonical, production‑safe names every pod should use.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Kafka&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;kafka.default.svc.cluster.local:9092
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If using a dedicated namespace:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;kafka.data.svc.cluster.local:9092
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Zookeeper&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;zookeeper.default.svc.cluster.local:2181
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kafka Connect&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;connect.default.svc.cluster.local:8083
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Elasticsearch&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;elasticsearch.default.svc.cluster.local:9200
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If using a StatefulSet with headless service:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;elasticsearch-0.elasticsearch.default.svc.cluster.local:9200
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kibana&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;kibana.default.svc.cluster.local:5601
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;MDM ETL Jobs&lt;br&gt;
Jobs should reference Kafka and Elasticsearch via DNS:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;kafka.default.svc.cluster.local:9092
elasticsearch.default.svc.cluster.local:9200
Bronze / Silver / Gold Storage
If using object storage:
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;minio.default.svc.cluster.local:9000
If using HDFS‑style:
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;namenode.default.svc.cluster.local:8020
2. How Docker Compose Can Simulate Kubernetes‑Style DNS
This is the trick that makes your local dev behave like a cluster.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Rule: Use service names, not localhost&lt;br&gt;
Docker Compose automatically creates an internal DNS zone where each service name resolves like a Kubernetes Service.&lt;/p&gt;
&lt;p&gt;Example docker‑compose.yml&lt;br&gt;
yaml&lt;/p&gt;
&lt;p&gt;services:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;  kafka:
    image: confluentinc/cp-kafka
    ports:
      - &quot;9092:9092&quot;

  zookeeper:
    image: confluentinc/cp-zookeeper
    ports:
      - &quot;2181:2181&quot;

  connect:
    image: confluentinc/cp-kafka-connect
    depends_on:
      - kafka
      - zookeeper
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Inside the network, these DNS names work:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;kafka:9092
zookeeper:2181
connect:8083
elasticsearch:9200
kibana:5601
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Exactly like Kubernetes:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;kafka.default.svc.cluster.local:9092
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;3-the-golden-rule-for-dev-ci-cd-kubernetes&quot;&gt;3. The Golden Rule for Dev → CI/CD → Kubernetes&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Never use localhost.&lt;br&gt;
Always use service names.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;docker-&quot;&gt;Docker:&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;kafka:9092
elasticsearch:9200
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;kubernetes-&quot;&gt;Kubernetes:&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;kafka.default.svc.cluster.local:9092
elasticsearch.default.svc.cluster.local:9200
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your code never changes — only the environment does.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;One‑line: Day zero.&lt;/p&gt;
&lt;p&gt;Two‑words: DNS first.&lt;/p&gt;
&lt;p&gt;Business analogy: If production uses street addresses, you don’t train your team on “my house, my room, my desk.”&lt;/p&gt;
&lt;p&gt;Direct answer (tight, mechanical, architect‑grade)&lt;br&gt;
Teams should switch to service‑style DNS from the very first local prototype, long before CI/CD or Kubernetes enter the picture.&lt;/p&gt;
&lt;p&gt;Because the moment you allow localhost:9092 into the code path, you’ve already baked in a failure mode:&lt;/p&gt;
&lt;p&gt;CI/CD → breaks&lt;/p&gt;
&lt;p&gt;Multi‑node cluster → breaks&lt;/p&gt;
&lt;p&gt;Sidecar networking → breaks&lt;/p&gt;
&lt;p&gt;Jobs/CronJobs → break&lt;/p&gt;
&lt;p&gt;Scaling → breaks&lt;/p&gt;
&lt;p&gt;Canary deploys → break&lt;/p&gt;
&lt;p&gt;Localhost is a lie in distributed systems.&lt;br&gt;
It only works on a laptop because Docker Compose simulates a fake single‑machine universe.&lt;/p&gt;
&lt;p&gt;The correct development sequence&lt;/p&gt;
&lt;h3 id=&quot;1-dev-environment-docker-&quot;&gt;1. Dev environment (Docker)&lt;/h3&gt;
&lt;p&gt;Use:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;kafka:9092
elasticsearch:9200
zookeeper:2181
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Never:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;localhost:9092
127.0.0.1:9200
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;2-ci-cd&quot;&gt;2. CI/CD&lt;/h3&gt;
&lt;p&gt;Use the same names:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;kafka:9092
elasticsearch:9200
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Your pipeline becomes cluster‑ready without changing a single line.&lt;/p&gt;
&lt;h3 id=&quot;3-kubernetes&quot;&gt;3. Kubernetes&lt;/h3&gt;
&lt;p&gt;DNS becomes:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-code&quot;&gt;kafka.svc.cluster.local:9092
elasticsearch.svc.cluster.local:9200
Same pattern, zero rewrites.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Why “DNS from day zero” is the only safe rule&lt;br&gt;
Eliminates environment drift&lt;/p&gt;
&lt;p&gt;Prevents pipeline failures&lt;/p&gt;
&lt;p&gt;Makes ETL jobs portable&lt;/p&gt;
&lt;p&gt;Avoids rewriting configs during migration&lt;/p&gt;
&lt;p&gt;Forces distributed‑system thinking early&lt;/p&gt;
&lt;p&gt;Protects MDM lineage and auditability&lt;/p&gt;
&lt;p&gt;If you wait until Kubernetes to fix localhost assumptions, you’re already in trouble — because your entire pipeline has been trained to believe in a topology that doesn’t exist in production.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/11450/dns-the-phonebook-of-the-internet</guid>
<pubDate>Wed, 11 Feb 2026 12:14:10 +0000</pubDate>
</item>
<item>
<title>Docker‑to‑Kubernetes failure points: Where Docker Assumptions Break in Kubernetes</title>
<link>https://coderlegion.com/11385/docker-to-kubernetes-failure-points-where-docker-assumptions-break-in-kubernetes</link>
<description>&lt;h2 id=&quot;docker-vs-kubernetes-for-kafka-elk-mdm&quot;&gt;Docker vs Kubernetes for Kafka + ELK + MDM&lt;/h2&gt;
&lt;h3 id=&quot;docker-assumptions&quot;&gt;Docker assumptions&lt;/h3&gt;
&lt;p&gt;[Docker Host: localhost]&lt;br&gt;
|&lt;br&gt;
|-- Kafka (ports: 9092:9092) -&amp;gt; localhost access OK&lt;br&gt;
|-- Zookeeper (ports: 2181:2181)&lt;br&gt;
|-- Connect (depends_on: Kafka, Zookeeper)&lt;br&gt;
|-- Elasticsearch (ports: 9200:9200)&lt;br&gt;
|-- Kibana (ports: 5601:5601)&lt;/p&gt;
&lt;h4 id=&quot;assumptions-docker-makes-here-&quot;&gt;Assumptions Docker makes here:&lt;/h4&gt;
&lt;p&gt;Single machine → IPs are predictable&lt;br&gt;
localhost can reach all services via host ports&lt;br&gt;
Startup order partially controlled by depends_on&lt;br&gt;
No strict health checks → app assumes services are ready&lt;br&gt;
Volumes persist across container restarts, host storage available&lt;br&gt;
latest images work fine&lt;br&gt;
Ports do not collide (developer responsibility)&lt;br&gt;
CI/CD not enforced → dev environment is “safe”&lt;/p&gt;
&lt;p&gt;What can break in CI/CD / Kubernetes:&lt;/p&gt;
&lt;p&gt;localhost:9092 in Connect fails → Kafka unreachable&lt;br&gt;
Startup race → pipelines try to read before Kafka is ready&lt;br&gt;
Host port collisions if multiple builds run simultaneously&lt;br&gt;
Volumes may not exist or behave differently → Bronze/Silver/Gold data lost&lt;/p&gt;
&lt;h3 id=&quot;kubernetes-assumptions&quot;&gt;Kubernetes assumptions&lt;/h3&gt;
&lt;p&gt;[Cluster: multi-node]&lt;br&gt;
|&lt;br&gt;
|-- Pod: Kafka&lt;br&gt;
|     - ephemeral IP&lt;br&gt;
|     - service: kafka.svc.cluster.local:9092&lt;br&gt;
|     - StatefulSet for persistence&lt;br&gt;
|&lt;br&gt;
|-- Pod: Zookeeper&lt;br&gt;
|     - StatefulSet&lt;br&gt;
|&lt;br&gt;
|-- Pod: Connect&lt;br&gt;
|     - Deployment / replica&lt;br&gt;
|     - readinessProbe: wait for Kafka&lt;br&gt;
|&lt;br&gt;
|-- Pod: Elasticsearch&lt;br&gt;
|     - StatefulSet&lt;br&gt;
|     - PVC for data&lt;br&gt;
|&lt;br&gt;
|-- Pod: Kibana&lt;br&gt;
|     - Deployment&lt;br&gt;
|&lt;br&gt;
|-- MDM ETL Jobs&lt;br&gt;
|     - run as Jobs / CronJobs&lt;br&gt;
|     - read Kafka via service discovery&lt;/p&gt;
&lt;p&gt;Kubernetes assumptions enforced here:&lt;/p&gt;
&lt;p&gt;Pods ephemeral → localhost cannot reach other services&lt;br&gt;
IPs change → must use service DNS&lt;br&gt;
Startup order not guaranteed → readiness/liveness probes required&lt;br&gt;
Pods can fail → apps must retry / be idempotent&lt;br&gt;
Volumes are externalized via PVC → pods assume statelessness&lt;br&gt;
No shared host ports → dynamic service ports or ClusterIP used&lt;br&gt;
Scaling / replicas expected → apps must handle multiple consumers&lt;br&gt;
Secrets/configs injected → apps cannot rely on local .env&lt;br&gt;
Potential failures if Docker assumptions remain:&lt;br&gt;
Connect tries localhost:9092 → fails&lt;br&gt;
ETL Jobs start before Kafka is ready → missing data&lt;br&gt;
MDM pipeline loses state if volume not properly configured → corrupted Bronze/Silver/Gold&lt;br&gt;
Kibana cannot reach Elasticsearch → wrong host/IP&lt;br&gt;
Scaling Kafka / Connect fails → race conditions&lt;/p&gt;
&lt;h3 id=&quot;summary-table-where-things-break&quot;&gt;Summary Table: Where things break&lt;/h3&gt;
&lt;p&gt;╔═════════════════════════════╗&lt;br&gt;
║ LAYER                                                              ║&lt;br&gt;
╠═════════════════════════════╣&lt;br&gt;
║ Networking                                                       ║&lt;br&gt;
║ Docker: localhost works                                   ║&lt;br&gt;
║ Kubernetes: localhost isolated; DNS required  ║&lt;br&gt;
║ Break: Kafka Connect cannot reach Kafka       ║&lt;br&gt;
╚═════════════════════════════╝&lt;/p&gt;
&lt;p&gt;╔═════════════════════════════╗&lt;br&gt;
║ Startup order                                                    ║&lt;br&gt;
╠═════════════════════════════╣&lt;br&gt;
║ Docker: depends_on works                             ║&lt;br&gt;
║ Kubernetes: startup unordered                        ║&lt;br&gt;
║ Break: ETL jobs fail on unavailable source      ║&lt;br&gt;
╚═════════════════════════════╝&lt;/p&gt;
&lt;p&gt;╔═════════════════════════════╗&lt;br&gt;
║ State                                                                 ║&lt;br&gt;
╠═════════════════════════════╣&lt;br&gt;
║ Docker: local volumes                                      ║&lt;br&gt;
║ Kubernetes: pods ephemeral; use PVs           ║&lt;br&gt;
║ Break: Bronze/Silver/Gold lost on restart         ║&lt;br&gt;
╚═════════════════════════════╝&lt;/p&gt;
&lt;p&gt;╔═════════════════════════════╗&lt;br&gt;
║ Port binding                                                      ║&lt;br&gt;
╠═════════════════════════════╣&lt;br&gt;
║ Docker: host ports available                             ║&lt;br&gt;
║ Kubernetes: dynamic ports; cluster network    ║&lt;br&gt;
║ Break: port collision or misrouting                    ║&lt;br&gt;
╚═════════════════════════════╝&lt;/p&gt;
&lt;p&gt;╔═════════════════════════════╗&lt;br&gt;
║ Scaling                                                              ║&lt;br&gt;
╠═════════════════════════════╣&lt;br&gt;
║ Docker: manual / optional                                ║&lt;br&gt;
║ Kubernetes: replicas normal                            ║&lt;br&gt;
║ Break: consumer duplication / missed msgs    ║&lt;br&gt;
╚═════════════════════════════╝&lt;/p&gt;
&lt;p&gt;╔═════════════════════════════╗&lt;br&gt;
║ Config                                                               ║&lt;br&gt;
╠═════════════════════════════╣&lt;br&gt;
║ Docker: .env files                                              ║&lt;br&gt;
║ Kubernetes: ConfigMaps / Secrets                  ║&lt;br&gt;
║ Break: jobs fail; app misconfigured                  ║&lt;br&gt;
╚═════════════════════════════╝&lt;/p&gt;
&lt;p&gt;╔═════════════════════════════╗&lt;br&gt;
║ Health                                                               ║&lt;br&gt;
╠═════════════════════════════╣&lt;br&gt;
║ Docker: optional                                               ║&lt;br&gt;
║ Kubernetes: readiness/liveness required         ║&lt;br&gt;
║ Break: app starts too early → errors                ║&lt;br&gt;
╚═════════════════════════════╝&lt;/p&gt;
&lt;p&gt;Mental picture&lt;/p&gt;
&lt;h3 id=&quot;docker-compose-dev-&quot;&gt;Docker Compose (dev)       &lt;/h3&gt;
&lt;p&gt;Single host                                              &lt;br&gt;
localhost:9092 → Kafka                          &lt;br&gt;
depends_on → partial order                    &lt;br&gt;
Volumes → local paths                            &lt;br&gt;
Ports → host mapped                              &lt;br&gt;
App assumes success                             &lt;br&gt;
Key insight&lt;/p&gt;
&lt;h3 id=&quot;kubernetes-prod-&quot;&gt;Kubernetes (prod)&lt;/h3&gt;
&lt;p&gt;Multi-node cluster&lt;br&gt;
kafka.svc.cluster.local:9092&lt;br&gt;
readiness_Probe + retries&lt;br&gt;
Persistent_Volumes / Stateful_Sets&lt;br&gt;
Ports abstracted via Services&lt;br&gt;
App assumes failure / retries&lt;/p&gt;
&lt;h3 id=&quot;closing-remarks&quot;&gt;Closing Remarks&lt;/h3&gt;
&lt;p&gt;Docker Compose hides bad assumptions: “works on my laptop”&lt;br&gt;
Kubernetes exposes them: “does your pipeline really work anywhere?”&lt;/p&gt;
&lt;h2 id=&quot;warning-&quot;&gt;Warning:&lt;/h2&gt;
&lt;p&gt;In an enterprise MDM pipeline, ignoring these differences = data loss, compliance violations, or audit failures.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/11385/docker-to-kubernetes-failure-points-where-docker-assumptions-break-in-kubernetes</guid>
<pubDate>Tue, 10 Feb 2026 14:52:23 +0000</pubDate>
</item>
<item>
<title>ETL vs ELT — Why Notebook Placement Matters  Body / Content: Yes — the placement of your Databricks</title>
<link>https://coderlegion.com/11185/etl-vs-elt-why-notebook-placement-matters-body-content-yes-the-placement-your-databricks</link>
<description>&lt;h2 id=&quot;etl-vs-elt-why-notebook-placement-matters&quot;&gt;ETL vs ELT — Why Notebook Placement Matters&lt;/h2&gt;
&lt;h3 id=&quot;body-content-&quot;&gt;Body / Content:&lt;/h3&gt;
&lt;p&gt;The placement of your Databricks notebooks determines whether your pipeline behaves like ETL or ELT.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If Databricks runs after loading data into the lake, it’s ELT.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If Databricks runs&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt; before loading transformed data, it’s ETL.&lt;/p&gt;
&lt;p&gt;Business Analogy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Clean vegetables before putting them in the fridge → ETL&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Dump everything in the fridge and clean later → ELT&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Architecture Mapping:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;RAW → BRONZE in ADF = Extract + Load (EL)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SILVER → GOLD in Data-bricks = Transform (T)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;✅ This makes your pipeline ELT, the modern standard:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cheap storage Scalable compute Delta Lake supports late&lt;br&gt;
transformations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Notebooks preserve raw data and give flexibility&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/11185/etl-vs-elt-why-notebook-placement-matters-body-content-yes-the-placement-your-databricks</guid>
<pubDate>Fri, 06 Feb 2026 14:09:12 +0000</pubDate>
</item>
</channel>
</rss>