<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Baran KİBAR on Medium]]></title>
        <description><![CDATA[Stories by Baran KİBAR on Medium]]></description>
        <link>https://medium.com/@barankibarr?source=rss-26c15f7f0eda------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*Dy1OFXoG_eAPQCEcUMZ0qA.jpeg</url>
            <title>Stories by Baran KİBAR on Medium</title>
            <link>https://medium.com/@barankibarr?source=rss-26c15f7f0eda------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 20 May 2026 10:36:06 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@barankibarr/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Go Runtime’s Container Awareness: A Deep Dive into How It Works]]></title>
            <link>https://medium.com/@barankibarr/go-runtimes-container-awareness-a-deep-dive-into-how-it-works-4e7bdfad2335?source=rss-26c15f7f0eda------2</link>
            <guid isPermaLink="false">https://medium.com/p/4e7bdfad2335</guid>
            <category><![CDATA[containerization]]></category>
            <category><![CDATA[tech-blog]]></category>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[cloud-native]]></category>
            <category><![CDATA[runtime]]></category>
            <dc:creator><![CDATA[Baran KİBAR]]></dc:creator>
            <pubDate>Thu, 09 Oct 2025 15:15:58 GMT</pubDate>
            <atom:updated>2025-10-09T15:15:58.727Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Pb_Laau8opEVN38beeTitg.png" /></figure><p>For years, Go’s runtime behaved like it was running on a bare-metal machine — blissfully unaware of container boundaries.</p><p>When your Go app started, the runtime looked at the <strong>total number of CPU cores on the host system</strong> and used that to set GOMAXPROCS, which controls how many OS threads can execute Go code simultaneously.</p><p>That made sense for physical servers.<br> But in modern containerized environments like <strong>Docker</strong> or <strong>Kubernetes</strong>, this created a silent performance problem:</p><blockquote>Go thought it could use all host CPUs, but the container actually had only a limited CPU quota.</blockquote><p>As a result, Go’s scheduler would spawn too many threads and goroutines, leading to <strong>CPU throttling</strong>, uneven performance, and wasted scheduling overhead.</p><h3>The Fix: Go 1.25 Brings Container Awareness</h3><p>Starting with <strong>Go 1.25</strong>, the runtime on Linux has become <strong>cgroup-aware</strong> — meaning it can now detect and respect CPU limits enforced by the container runtime.</p><p>This change may sound small, but it’s a major step forward for Go in cloud-native environments.</p><p>Here’s what’s new:</p><h3>1. Automatic Cgroup Detection</h3><p>When a Go program starts, the runtime checks if it’s running under Linux cgroups.<br> If a CPU quota is defined in that cgroup, it will calculate the <strong>effective number of CPUs</strong> available to the process using one of the following:</p><ul><li><strong>Cgroup v1:</strong><br> /sys/fs/cgroup/cpu/cpu.cfs_quota_us<br> /sys/fs/cgroup/cpu/cpu.cfs_period_us</li><li><strong>Cgroup v2:</strong><br> /sys/fs/cgroup/cpu.max</li></ul><p>From these values, the runtime computes:</p><blockquote>effective_cpus = cpu.cfs_quota_us / cpu.cfs_period_us</blockquote><p>If the quota is unlimited (for example, -1), it defaults back to using the full host CPU count.</p><h3>2. Dynamic GOMAXPROCS Adjustment</h3><p>Once Go knows how many CPUs the container is allowed to use, it automatically sets GOMAXPROCS to that number.</p><p>But it doesn’t stop there — the runtime also <strong>periodically re-checks</strong> these limits (roughly every 30 seconds).</p><p>That means if your container’s resource configuration changes — for example, you update CPU limits in a Kubernetes Deployment — Go will detect it and update GOMAXPROCS dynamically at runtime.</p><p>This prevents the need for restarts and ensures the scheduler always reflects the latest resource configuration.</p><h3>3. Respect for Manual Overrides</h3><p>If you manually call runtime.GOMAXPROCS(n) in your code, the automatic detection logic is <strong>disabled</strong>.</p><p>This is intentional — it gives developers full control if they prefer to override runtime behavior manually (e.g., for testing or benchmarking).</p><h3>4. New GODEBUG Flags for Fine Control</h3><p>Go introduces new environment variables to let you tune or disable container awareness:</p><ul><li>GODEBUG=containermaxprocs=0<br> → Disables cgroup detection (runtime ignores container CPU quotas).</li><li>GODEBUG=updatemaxprocs=0<br> → Disables periodic updates (runtime reads cgroup limits only once at startup).</li></ul><p>These can be useful when debugging, profiling, or running Go in unusual environments (e.g., inside privileged system containers or CI/CD pipelines).</p><h3>5. Improved Runtime Efficiency</h3><p>Under the hood, the runtime now <strong>caches file descriptors</strong> for cgroup files, rather than opening and closing them on each read.</p><p>This optimization reduces syscall overhead and improves performance, especially in systems where periodic updates are enabled.</p><h3>What Happens Inside the Runtime</h3><p>Let’s summarize what the runtime actually does during initialization:</p><ol><li><strong>Startup:</strong> When the program starts, Go runtime reads CPU quota and period values from cgroup files.</li><li><strong>Computation:</strong> It divides quota by period to get the effective number of CPUs.</li><li><strong>Comparison:</strong> It compares this number to runtime.NumCPU() (which reflects host CPUs).</li><li><strong>Selection:</strong> It sets GOMAXPROCS to the smaller value between the two.</li><li><strong>Reevaluation:</strong> Every ~30 seconds, it checks again. If limits changed, it updates GOMAXPROCS.</li></ol><p>This logic ensures that Go’s internal scheduler and garbage collector remain properly balanced relative to the actual CPU resources available.</p><h3>Example Scenario</h3><p>Imagine your Kubernetes deployment defines this resource limit:</p><pre>resources:<br>  limits:<br>    cpu: &quot;2&quot;<br>  requests:<br>    cpu: &quot;1&quot;</pre><p>Your pod will be placed in a cgroup with a quota equivalent to roughly 2 CPUs.<br> Before Go 1.25, the runtime might still assume 16 CPUs if that’s what the node had — over-scheduling goroutines and wasting cycles.</p><p>Now, with container awareness, Go sees only 2 CPUs and automatically sets:</p><pre>runtime.GOMAXPROCS() // = 2</pre><p>This small change leads to a big improvement in performance stability and latency predictability.</p><h3>Important Caveats</h3><ul><li><strong>Linux-only feature:</strong> Windows and macOS do not use cgroups.</li><li>If you explicitly set GOMAXPROCS, automatic behavior is skipped.</li><li>If your quota is fractional (e.g., 0.5 CPU), Go rounds up to 1.</li><li>This feature does <strong>not</strong> expose a “I’m running inside a container” boolean — it only reads resource limits.</li><li>Works with both <strong>Docker</strong> and <strong>Kubernetes</strong>, as long as cgroups are enabled.</li></ul><h3>Why This Matters for Cloud-Native Go Apps</h3><p>This feature makes Go much more predictable in containerized and multi-tenant environments.</p><p>In the past, you had to manually detect container limits (using libraries like <a href="https://github.com/uber-go/automaxprocs">uber-go/automaxprocs</a>) to avoid over-scheduling.<br> Now, that logic is built into the standard runtime itself.</p><p>As a result:</p><ul><li>You get better CPU utilization under quotas.</li><li>You avoid unnecessary throttling from the kernel’s CFS scheduler.</li><li>Your latency profiles become smoother and more predictable.</li><li>You no longer need an external dependency to tune GOMAXPROCS.</li></ul><p>This is especially valuable in high-throughput microservices, telemetry collectors, or any Go service deployed on Kubernetes nodes with tight CPU limits.</p><h3>Final Thoughts</h3><p>Go’s new container awareness represents a subtle yet significant evolution of the runtime.<br> Instead of blindly trusting the host environment, the runtime now reacts intelligently to real resource constraints — aligning Go more closely with modern cloud-native infrastructure principles.</p><p>As of <strong>Go 1.25</strong>, the runtime on Linux automatically detects and respects <strong>cgroup CPU limits</strong>. It reads quota and period values from <strong>cgroup v1</strong> (cpu.cfs_quota_us, cpu.cfs_period_us) or <strong>v2</strong> (cpu.max), computes the <strong>effective CPU capacity</strong>, and adjusts GOMAXPROCS accordingly. It also <strong>periodically re-checks</strong> these values to stay in sync with container limit changes, unless manually overridden or disabled via GODEBUG flags.</p><blockquote>In essence, the Go runtime is no longer <em>just running</em> — <strong>it’s listening to the container.</strong></blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4e7bdfad2335" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Terraform vs Ansible — What’s the Real Difference?]]></title>
            <link>https://blog.stackademic.com/terraform-vs-ansible-whats-the-real-difference-c1150932a7fb?source=rss-26c15f7f0eda------2</link>
            <guid isPermaLink="false">https://medium.com/p/c1150932a7fb</guid>
            <category><![CDATA[infrastructure-as-code]]></category>
            <category><![CDATA[iac]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[terraform]]></category>
            <category><![CDATA[ansible]]></category>
            <dc:creator><![CDATA[Baran KİBAR]]></dc:creator>
            <pubDate>Wed, 16 Apr 2025 08:20:11 GMT</pubDate>
            <atom:updated>2025-04-18T13:39:24.248Z</atom:updated>
            <content:encoded><![CDATA[<h3>Terraform vs Ansible — What’s the Real Difference?</h3><p>When you first get into Infrastructure as Code (IaC), you’ll probably hear a lot about tools like <strong>Terraform</strong> and <strong>Ansible</strong>. At first, it might seem like they’re doing the same thing — automating your infrastructure. But the truth is, they have very <strong>different purposes</strong>, and understanding those differences is <strong>key</strong> to building scalable, reliable environments.</p><p>So let’s break it down: What do these tools actually do, where do they overlap, and can one replace the other?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5oGQxcPB1RQWwtWbU18tow.png" /></figure><h3>1. What Terraform Does — <strong>Provisioning Tools</strong></h3><p>Terraform is a <strong>provisioning tool</strong>, which means it’s responsible for <strong>creating and managing infrastructure resources</strong>.</p><blockquote>Think of Terraform as the one who builds the house: walls, roof, plumbing, electricity — all the foundational stuff.</blockquote><h4>What Terraform can do:</h4><ul><li>Create cloud resources (VMs, networks, load balancers, databases, etc.)</li><li>Work across multiple cloud providers (AWS, Azure, GCP, etc.)</li><li>Keep track of what it created (using something called a “state file”)</li></ul><h4>Real-life example:</h4><p>Let’s say you want to launch a production environment:</p><ul><li>One VPC</li><li>Two Subnets (in different availability zones)</li><li>One Internet Gateway and Route Tables</li><li>One Security Group (Allowing HTTP and SSH)</li><li>Three EC2 Instances via Auto Scaling Group</li><li>One Application Load Balancer</li><li>One RDS PostgreSQL Database</li></ul><p><strong>Terraform</strong> can do all of this automatically from a .tf file. Just write it once, and apply it anytime. It&#39;s repeatable, and version-controlled.</p><p>main.tf — Networking and Security:</p><pre>provider &quot;aws&quot; {<br>  region = &quot;us-east-1&quot;<br>}<br><br># VPC<br>resource &quot;aws_vpc&quot; &quot;main&quot; {<br>  cidr_block           = &quot;10.0.0.0/16&quot;<br>  enable_dns_hostnames = true<br>  tags = {<br>    Name = &quot;production-vpc&quot;<br>  }<br>}<br><br># Subnets<br>resource &quot;aws_subnet&quot; &quot;subnet1&quot; {<br>  vpc_id            = aws_vpc.main.id<br>  cidr_block        = &quot;10.0.1.0/24&quot;<br>  availability_zone = &quot;us-east-1a&quot;<br>  tags = {<br>    Name = &quot;subnet-1&quot;<br>  }<br>}<br><br>resource &quot;aws_subnet&quot; &quot;subnet2&quot; {<br>  vpc_id            = aws_vpc.main.id<br>  cidr_block        = &quot;10.0.2.0/24&quot;<br>  availability_zone = &quot;us-east-1b&quot;<br>  tags = {<br>    Name = &quot;subnet-2&quot;<br>  }<br>}<br><br># Internet Gateway<br>resource &quot;aws_internet_gateway&quot; &quot;gw&quot; {<br>  vpc_id = aws_vpc.main.id<br>}<br><br># Route Table<br>resource &quot;aws_route_table&quot; &quot;rt&quot; {<br>  vpc_id = aws_vpc.main.id<br><br>  route {<br>    cidr_block = &quot;0.0.0.0/0&quot;<br>    gateway_id = aws_internet_gateway.gw.id<br>  }<br>}<br><br># Route Table Associations<br>resource &quot;aws_route_table_association&quot; &quot;a1&quot; {<br>  subnet_id      = aws_subnet.subnet1.id<br>  route_table_id = aws_route_table.rt.id<br>}<br><br>resource &quot;aws_route_table_association&quot; &quot;a2&quot; {<br>  subnet_id      = aws_subnet.subnet2.id<br>  route_table_id = aws_route_table.rt.id<br>}<br><br># Security Group<br>resource &quot;aws_security_group&quot; &quot;instance_sg&quot; {<br>  name        = &quot;instance-sg&quot;<br>  description = &quot;Allow HTTP, SSH&quot;<br>  vpc_id      = aws_vpc.main.id<br><br>  ingress {<br>    from_port   = 22<br>    to_port     = 22<br>    protocol    = &quot;tcp&quot;<br>    cidr_blocks = [&quot;0.0.0.0/0&quot;]<br>  }<br><br>  ingress {<br>    from_port   = 80<br>    to_port     = 80<br>    protocol    = &quot;tcp&quot;<br>    cidr_blocks = [&quot;0.0.0.0/0&quot;]<br>  }<br><br>  egress {<br>    from_port   = 0<br>    to_port     = 0<br>    protocol    = &quot;-1&quot;<br>    cidr_blocks = [&quot;0.0.0.0/0&quot;]<br>  }<br>}</pre><p>ec2.tf — Compute Resources:</p><pre># Launch Template<br>resource &quot;aws_launch_template&quot; &quot;web_template&quot; {<br>  name_prefix   = &quot;web-template-&quot;<br>  image_id      = &quot;ami-***&quot; # Replace with latest Amazon Linux or Ubuntu AMI<br>  instance_type = &quot;t3.micro&quot;<br><br>  vpc_security_group_ids = [aws_security_group.instance_sg.id]<br><br>  tag_specifications {<br>    resource_type = &quot;instance&quot;<br>    tags = {<br>      Name = &quot;web-server&quot;<br>    }<br>  }<br><br>  user_data = base64encode(&lt;&lt;-EOF<br>              #!/bin/bash<br>              sudo yum update -y<br>              sudo yum install -y httpd<br>              sudo systemctl enable httpd<br>              sudo systemctl start httpd<br>              echo &quot;&lt;h1&gt;Web Server Running&lt;/h1&gt;&quot; &gt; /var/www/html/index.html<br>            EOF<br>  )<br>}<br><br># Auto Scaling Group (3 Instances)<br>resource &quot;aws_autoscaling_group&quot; &quot;web_asg&quot; {<br>  desired_capacity     = 3<br>  max_size             = 3<br>  min_size             = 3<br>  vpc_zone_identifier  = [aws_subnet.subnet1.id, aws_subnet.subnet2.id]<br>  launch_template {<br>    id      = aws_launch_template.web_template.id<br>    version = &quot;$Latest&quot;<br>  }<br>  target_group_arns = [aws_lb_target_group.web_tg.arn]<br>  health_check_type = &quot;EC2&quot;<br>}<br><br># Load Balancer<br>resource &quot;aws_lb&quot; &quot;web_lb&quot; {<br>  name               = &quot;web-lb&quot;<br>  internal           = false<br>  load_balancer_type = &quot;application&quot;<br>  security_groups    = [aws_security_group.instance_sg.id]<br>  subnets            = [aws_subnet.subnet1.id, aws_subnet.subnet2.id]<br>}<br><br>resource &quot;aws_lb_target_group&quot; &quot;web_tg&quot; {<br>  name     = &quot;web-tg&quot;<br>  port     = 80<br>  protocol = &quot;HTTP&quot;<br>  vpc_id   = aws_vpc.main.id<br>}<br><br>resource &quot;aws_lb_listener&quot; &quot;web_listener&quot; {<br>  load_balancer_arn = aws_lb.web_lb.arn<br>  port              = &quot;80&quot;<br>  protocol          = &quot;HTTP&quot;<br><br>  default_action {<br>    type             = &quot;forward&quot;<br>    target_group_arn = aws_lb_target_group.web_tg.arn<br>  }<br>}</pre><p>rds.tf — PostgreSQL:</p><pre>resource &quot;aws_db_subnet_group&quot; &quot;default&quot; {<br>  name       = &quot;main-db-subnet-group&quot;<br>  subnet_ids = [aws_subnet.subnet1.id, aws_subnet.subnet2.id]<br>}<br><br>resource &quot;aws_db_instance&quot; &quot;postgres&quot; {<br>  identifier        = &quot;production-db&quot;<br>  engine            = &quot;postgres&quot;<br>  instance_class    = &quot;db.t3.micro&quot;<br>  allocated_storage = 20<br>  username          = &quot;admin&quot;<br>  password          = &quot;supersecurepassword&quot;<br>  db_subnet_group_name = aws_db_subnet_group.default.name<br>  vpc_security_group_ids = [aws_security_group.instance_sg.id]<br>  skip_final_snapshot = true<br>}</pre><p>outputs.tf — Useful Outputs:</p><pre>output &quot;load_balancer_dns_name&quot; {<br>  value = aws_lb.web_lb.dns_name<br>}<br><br>output &quot;db_endpoint&quot; {<br>  value = aws_db_instance.postgres.endpoint<br>}</pre><h3>2. What Ansible Does — Configuration Management Tools</h3><p>Ansible is for <strong>configuration management</strong>. In simple terms: it takes machines that already exist, and <strong>sets them up</strong>.</p><blockquote><em>Think of Ansible as the person who moves in the furniture, sets up the TV, configures the Wi-Fi, and hangs the paintings.</em></blockquote><h4>What Ansible can do:</h4><ul><li>Install necessary packages</li><li>Deploy the application code</li><li>Configure environment variables and application settings</li><li>Start necessary services</li></ul><p>After provisioning with Terraform, <strong>Ansible</strong> takes over for configuration management. It uses the public IPs or DNS names of the EC2 instances to:</p><p>Inventory Example (inventory.ini):</p><pre>[webservers]<br>web1 ansible_host=&lt;ec2-instance-public-ip-1&gt;<br>web2 ansible_host=&lt;ec2-instance-public-ip-2&gt;<br>web3 ansible_host=&lt;ec2-instance-public-ip-3&gt;</pre><p>Playbook Example (site.yml):</p><pre>- name: Configure Web Servers<br>  hosts: webservers<br>  become: yes<br>  tasks:<br>    - name: INSTALL APACHE<br>      yum:<br>        name: httpd<br>        state: present<br><br>    - name: COPY APPLICATION FILES<br>      copy:<br>        src: ./app/<br>        dest: /var/www/html/<br><br>    - name: START APACHE SERVICE<br>      service:<br>        name: httpd<br>        state: started<br>        enabled: true</pre><blockquote>This playbook is just a starting point. It can be extended with roles, templated configuration files, secret handling, and database connectivity tests.</blockquote><h3>Workflow Summary</h3><p><strong>1.Terraform Init &amp; Apply</strong>:</p><pre>terraform init<br>terraform apply -auto-approve</pre><p><strong>2.Extract EC2 IPs (from Terraform Outputs or AWS CLI)</strong></p><p>Extract public IPs or DNS names from Terraform outputs or use the AWS CLI.</p><p><strong>3.Configure Ansible Inventory (inventory.ini)</strong></p><p>Populate inventory.ini with the retrieved instance addresses.</p><p><strong>4.Run Ansible Playbook:</strong></p><pre>ansible-playbook -i inventory.ini site.yml</pre><p>This hybrid IaC approach ensures that:</p><ul><li>Infrastructure is <strong>provisioned repeatably</strong> with Terraform</li><li>Instances are <strong>configured consistently</strong> with Ansible</li></ul><p>Perfect for <strong>production deployments</strong>, <strong>testing environments</strong>, or <strong>CI/CD automation</strong>.</p><h3>Why This Workflow Works</h3><p>This hybrid Infrastructure as Code (IaC) approach offers the best of both worlds:</p><ul><li><strong>Terraform</strong> ensures infrastructure is <strong>declaratively provisioned</strong> and <strong>easily reproducible</strong>.</li><li><strong>Ansible</strong> guarantees instances are <strong>consistently configured</strong> and <strong>application-ready</strong>.</li></ul><p>Ideal for:</p><ul><li><strong>Production deployments</strong></li><li><strong>Test environments</strong></li><li><strong>CI/CD automation pipelines</strong></li></ul><h3>Can Terraform do what Ansible does?</h3><p><strong>Technically, yes — but you probably shouldn’t.</strong></p><p>Terraform does have a remote-exec feature where it can SSH into a server and run shell scripts. You <em>can</em> use it to install software, edit files, and more.</p><p>BUT:</p><ul><li>It’s not idempotent</li><li>It’s harder to manage at scale</li><li>It mixes concerns: infrastructure vs. configuration</li></ul><blockquote>Terraform <em>can</em> do basic setup, but it’s not designed for full-on system configuration.</blockquote><h3>Can Ansible do what Terraform does?</h3><p>Again: <strong>yes — but it’s not ideal.</strong></p><p>Ansible has cloud modules (ec2, azure_rm, etc.) to spin up resources like VMs, load balancers, etc. But it doesn’t keep track of the resources like Terraform does. There’s no state file. You have to manage that logic yourself.</p><p>It also gets more complicated when you’re working across multiple cloud providers.</p><blockquote>Ansible <em>can</em> provision resources, but Terraform is much better suited for it.</blockquote><h3>The Best Practice: Use Both</h3><p>Let’s say you’re deploying a new e-commerce app. Here’s a solid approach:</p><p><strong>1.Terraform</strong>:</p><ul><li>Set up the cloud environment (VPC, subnets, EC2, RDS, etc.)</li></ul><p><strong>2.Ansible</strong>:</p><ul><li>Configure the EC2 instances: install Node.js, deploy your app, start services.</li></ul><p>They’re both powerful, but they shine in <strong>different stages</strong> of the deployment pipeline.</p><h3>Finally:</h3><p>If Terraform is your <strong>architect and construction team</strong>, Ansible is your <strong>interior designer and electrician</strong>.</p><p>Trying to do everything with just one tool might work at first, but it gets messy fast. Use each tool for what it does best, and you’ll end up with a cleaner, more maintainable infrastructure.</p><h3>Thank you for being a part of the community</h3><p><em>Before you go:</em></p><ul><li>Be sure to <strong>clap</strong> and <strong>follow</strong> the writer ️👏<strong>️️</strong></li><li>Follow us: <a href="https://x.com/inPlainEngHQ"><strong>X</strong></a> | <a href="https://www.linkedin.com/company/inplainenglish/"><strong>LinkedIn</strong></a> | <a href="https://www.youtube.com/@InPlainEnglish"><strong>YouTube</strong></a> | <a href="https://newsletter.plainenglish.io/"><strong>Newsletter</strong></a> | <a href="https://open.spotify.com/show/7qxylRWKhvZwMz2WuEoua0"><strong>Podcast</strong></a> | <a href="https://differ.blog/inplainenglish"><strong>Differ</strong></a> | <a href="https://twitch.tv/inplainenglish"><strong>Twitch</strong></a></li><li><a href="https://cofeed.app/"><strong>Check out CoFeed, the smart way to stay up-to-date with the latest in tech</strong></a> <strong>🧪</strong></li><li><a href="https://differ.blog/"><strong>Start your own free AI-powered blog on Differ</strong></a> 🚀</li><li><a href="https://discord.gg/in-plain-english-709094664682340443"><strong>Join our content creators community on Discord</strong></a> 🧑🏻‍💻</li><li>For more content, visit <a href="https://plainenglish.io/"><strong>plainenglish.io</strong></a> + <a href="https://stackademic.com/"><strong>stackademic.com</strong></a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c1150932a7fb" width="1" height="1" alt=""><hr><p><a href="https://blog.stackademic.com/terraform-vs-ansible-whats-the-real-difference-c1150932a7fb">Terraform vs Ansible — What’s the Real Difference?</a> was originally published in <a href="https://blog.stackademic.com">Stackademic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using Multiple Istio Ingress Gateways]]></title>
            <link>https://medium.com/@barankibarr/using-multiple-istio-ingress-gateways-9b192f399e1d?source=rss-26c15f7f0eda------2</link>
            <guid isPermaLink="false">https://medium.com/p/9b192f399e1d</guid>
            <category><![CDATA[kubernetes-gateway]]></category>
            <category><![CDATA[ingress]]></category>
            <category><![CDATA[istio]]></category>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[k8s]]></category>
            <dc:creator><![CDATA[Baran KİBAR]]></dc:creator>
            <pubDate>Sun, 08 Sep 2024 05:53:55 GMT</pubDate>
            <atom:updated>2024-09-08T05:53:55.886Z</atom:updated>
            <content:encoded><![CDATA[<h3>Using Multiple Ingress Gateways</h3><p>This document explains how to configure and use multiple Ingress Gateways in an Istio environment.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DNv0U_yN2ABRtBz3R6O8xw.jpeg" /></figure><p><strong>1. Defining Multiple Ingress Gateways (Not Supported)</strong></p><p>Istio comes with a default Ingress Gateway. To use multiple Ingress Gateways, you can define additional gateways using IstioOperator resources. The following example demonstrates how to define two different Ingress Gateways.</p><pre>apiVersion: install.istio.io/v1alpha1<br>kind: IstioOperator<br>metadata:<br>  name: multi-ingress-gateway<br>  namespace: istio-system # The namespace where the Istio resources will be deployed, usually istio-system.<br>spec:<br>  components:<br>    ingressGateways:<br>      - name: ingressgateway-1 # The name of the Ingress Gateway.<br>        namespace: istio-system # The namespace in which this gateway will operate.<br>        enabled: true # Whether this gateway is enabled.<br>        label:<br>          istio: ingressgateway-1 # A label for the gateway. Useful for matching in VirtualService configurations.<br>        k8s:<br>          serviceAnnotations:<br>            service.beta.kubernetes.io/aws-load-balancer-internal: &quot;true&quot; # AWS-specific annotation to create an internal LoadBalancer.<br>          service:<br>            type: LoadBalancer # The type of Kubernetes service. LoadBalancer exposes the service externally with a cloud provider&#39;s load balancer.<br>            ports:<br>              - port: 80 # The port that the gateway will listen on for HTTP traffic.<br>                targetPort: 8080 # The target port in the Pod where the traffic will be directed.<br>                name: http # A name for the HTTP port.<br>              - port: 443 # The port for HTTPS traffic.<br>                targetPort: 8443 # The target port in the Pod for HTTPS traffic.<br>                name: https # A name for the HTTPS port.<br>            # externalTrafficPolicy: Local  # Ensures that traffic only leaves the node where the Pod is running, improving performance.<br>            # sessionAffinity: ClientIP  # Ensures that requests from the same client IP are routed to the same backend Pod.<br>      - name: ingressgateway-2<br>        namespace: istio-system<br>        enabled: true<br>        label:<br>          istio: ingressgateway-2<br>        k8s:<br>          service:<br>            type: LoadBalancer<br>            ports:<br>              - port: 80<br>                targetPort: 8080<br>                name: http<br>              - port: 443<br>                targetPort: 8443<br>                name: https</pre><p>Apply this YAML File:</p><pre>istioctl install -f *.yaml</pre><p><strong>2. Comprehensive Customization Options for Creating an Istio Ingress Gateway with Helm</strong> These customizations allow you to control how the gateway behaves, its networking configurations, security settings, and more. Below, I outline the various customization options available when creating an Istio Ingress Gateway using Helm. For more details, you can refer to the official Istio Helm chart documentation <a href="https://istio.io/latest/docs/setup/install/helm/">here</a>.</p><ul><li>Service Type: Configures the service type for the Ingress Gateway. Common options include LoadBalancer, NodePort, and ClusterIP.</li></ul><pre>--set service.type=LoadBalancer</pre><ul><li>Service Annotations: Allows you to add custom annotations to the service. This is often used for cloud-specific settings, such as specifying whether a load balancer should be internal.</li></ul><pre>--set serviceAnnotations.&quot;service\.beta\.kubernetes\.io/aws-load-balancer-internal&quot;=&quot;true&quot;</pre><ul><li>Port Configuration: gateways.istio-ingressgateway.ports: Customize the ports that the Ingress Gateway listens on. You can specify HTTP, HTTPS, TCP ...</li></ul><pre>--set gateways.istio-ingressgateway.ports[0].port=80 \<br>--set gateways.istio-ingressgateway.ports[0].targetPort=8080 \<br>--set gateways.istio-ingressgateway.ports[0].name=http</pre><ul><li>Node Port Configuration: service.nodePorts: If using NodePort, you can specify the exact node ports.</li></ul><pre>--set service.nodePorts.http=32080 \<br>--set service.nodePorts.https=32443</pre><ul><li>Load Balancer IP: loadBalancerIP: Specify a static IP for the load balancer, useful in scenarios where you need a fixed external IP.</li></ul><pre>--set loadBalancerIP=192.168.1.100</pre><ul><li>External Traffic Policy: externalTrafficPolicy: Controls how traffic is handled by the gateway, with options like Local or Cluster.</li></ul><pre>--set service.externalTrafficPolicy=Local</pre><ul><li>TLS Configuration: gateways.istio-ingressgateway.secretVolumes: Configure secret volumes for TLS certificates.`</li></ul><pre>--set gateways.istio-ingressgateway.secretVolumes[0].name=ingressgateway-certs \<br>--set gateways.istio-ingressgateway.secretVolumes[0].secretName=istio-ingressgateway-certs \<br>--set gateways.istio-ingressgateway.secretVolumes[0].mountPath=/etc/istio/ingressgateway-certs</pre><ul><li>SDS (Secret Discovery Service): sds.enabled: Enable SDS to dynamically provision and manage TLS certificates.</li></ul><pre>--set sds.enabled=true</pre><ul><li>Resource Requests and Limits: resources: Set CPU and memory requests and limits for the gateway’s pods.</li></ul><pre>--set resources.requests.cpu=500m \<br>--set resources.requests.memory=256Mi \<br>--set resources.limits.cpu=1000m \<br>--set resources.limits.memory=512Mi</pre><ul><li>Autoscaling: autoscaleEnabled: Enable or disable autoscaling for the gateway.</li></ul><pre>--set autoscaleEnabled=true \<br>--set autoscaleMin=2 \<br>--set autoscaleMax=5</pre><ul><li>Replica Count: replicaCount: Specify the number of replicas for the Ingress Gateway deployment.</li></ul><pre>--set replicaCount=3</pre><ul><li>Custom Labels: gateways.istio-ingressgateway.labels: Add custom labels to the Ingress Gateway resources for better management and identification.</li></ul><pre>--set gateways.istio-ingressgateway.labels.environment=production</pre><ul><li>Pod Node Selectors: gateways.istio-ingressgateway.podAnnotations: Annotate pods for custom scheduling.</li></ul><pre>--set gateways.istio-ingressgateway.nodeSelector.&quot;kubernetes\.io/os&quot;=linux</pre><ul><li>Access Logging: meshConfig.accessLogFile: Configure access logs for the Ingress Gateway.</li></ul><pre>--set meshConfig.accessLogFile=/dev/stdout</pre><ul><li>Prometheus Monitoring: prometheus.enabled: Enable Prometheus metrics for the gateway.</li></ul><pre>--set prometheus.enabled=true</pre><h3>Example:</h3><pre>helm install ingressgateway-2 istio/gateway -n istio-system \<br>  --set service.type=LoadBalancer \<br>  --set gateways.istio-ingressgateway.ports[0].port=80 \<br>  --set gateways.istio-ingressgateway.ports[0].targetPort=8080 \<br>  --set gateways.istio-ingressgateway.ports[0].name=http \<br>  --set gateways.istio-ingressgateway.ports[1].port=443 \<br>  --set gateways.istio-ingressgateway.ports[1].targetPort=8443 \<br>  --set gateways.istio-ingressgateway.ports[1].name=https</pre><pre>helm install ingressgateway-2 istio/gateway -n istio-system \<br>  --set autoscaleEnabled=true \<br>  --set autoscaleMin=2 \<br>  --set autoscaleMax=5 \<br>  --set replicaCount=3 \<br>  --set resources.requests.cpu=500m \<br>  --set resources.requests.memory=256Mi \<br>  --set resources.limits.cpu=1000m \<br>  --set resources.limits.memory=512Mi</pre><p><strong>3. Configuring Gateway and VirtualService</strong></p><p>To route traffic for each Ingress Gateway, you need to configure Gateway and VirtualService resources. The following example shows traffic routing for two different gateways.</p><p>virtualservice-gateway-1.yaml</p><pre>apiVersion: networking.istio.io/v1beta1<br>kind: Gateway<br>metadata:<br>  name: gateway-1 # This name must match the gateway referenced in the VirtualService<br>  namespace: default # This should be the same namespace as the VirtualService, or use fully qualified name in the VirtualService<br>spec:<br>  selector:<br>    istio: ingressgateway-1 # This label should match the label defined in the Ingress Gateway configuration<br>  servers:<br>    - port:<br>        number: 80 # The port that this Gateway will listen on<br>        name: http<br>        protocol: HTTP<br>      hosts:<br>        - &quot;internal.example.com&quot; # The host(s) this Gateway will accept traffic for</pre><pre># Gateway2.yaml<br>apiVersion: networking.istio.io/v1beta1<br>kind: Gateway<br>metadata:<br>  name: gateway-2<br>  namespace: default<br>spec:<br>  selector:<br>    istio: ingressgateway-2<br>  servers:<br>    - port:<br>        number: 80<br>        name: http<br>        protocol: HTTP<br>      hosts:<br>        - &quot;external.example.com&quot;</pre><p><strong>4. Routing Traffic with VirtualService</strong> Below are examples of two VirtualService configurations that route requests to specific services through the designated gateway based on the domain.</p><p>virtualservice-gateway-1.yaml</p><pre>apiVersion: networking.istio.io/v1beta1<br>kind: VirtualService<br>metadata:<br>  name: service-gateway-1 # The name of the VirtualService resource, unique within the namespace.<br>  namespace: default # The namespace where this VirtualService is applied.<br>spec:<br>  hosts:<br>    - &quot;internal.example.com&quot; # The host or domain this VirtualService applies to. Requests to this host will be routed based on the rules defined here.<br>  gateways:<br>    - gateway-1 # References the Gateway resource that handles incoming traffic. This must match the name of an existing Gateway.<br>  http:<br>    - match:<br>        - uri:<br>            prefix: / # Matches requests<br>      route:<br>        - destination:<br>            host: internal-service # The name of the service to which the traffic will be routed.<br>            port:<br>              number: 8080 # The port on the destination service that will receive the traffic.</pre><p>virtualservice-gateway-2.yaml</p><pre>apiVersion: networking.istio.io/v1beta1<br>kind: VirtualService<br>metadata:<br>  name: service-gateway-2<br>  namespace: default<br>spec:<br>  hosts:<br>    - &quot;external.example.com&quot;<br>  gateways:<br>    - gateway-2<br>  http:<br>    - match:<br>        - uri:<br>            prefix: /<br>      route:<br>        - destination:<br>            host: external-service<br>            port:<br>              number: 8080</pre><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9b192f399e1d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Server-Sent Events vs. WebSockets: Which One Should You Choose?]]></title>
            <link>https://blog.stackademic.com/server-sent-events-vs-websockets-which-one-should-you-choose-6dcd8bdfb4dd?source=rss-26c15f7f0eda------2</link>
            <guid isPermaLink="false">https://medium.com/p/6dcd8bdfb4dd</guid>
            <category><![CDATA[web-development]]></category>
            <category><![CDATA[server-sent-events]]></category>
            <category><![CDATA[websocket]]></category>
            <category><![CDATA[real-time-communication]]></category>
            <dc:creator><![CDATA[Baran KİBAR]]></dc:creator>
            <pubDate>Sat, 08 Jun 2024 14:22:35 GMT</pubDate>
            <atom:updated>2024-07-15T00:48:56.131Z</atom:updated>
            <content:encoded><![CDATA[<p>When building a web app that needs real-time communication, you’ve got two popular choices: Server-Sent Events (SSE) and WebSockets. Picking the right one can make a big difference in how smooth and efficient your app runs. Let’s break down what each of these does and figure out which one might be best for your project.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bzDo6Lh5DaltsbChANDH0g.png" /></figure><h3>What Are Server-Sent Events (SSE)?</h3><p>Server-Sent Events (SSE) let servers send updates to clients over a single HTTP connection. Think of it like the server pushing notifications to the client whenever there’s something new.</p><h4>Highlights of SSE:</h4><ol><li><strong>One-Way Street</strong>: SSE is great for sending updates from the server to the client. The client can’t send messages back through the same channel.</li><li><strong>Easy to Set Up</strong>: SSE uses regular HTTP, which makes it pretty straightforward to implement.</li><li><strong>Reconnects Automatically</strong>: If the connection drops, the SSE client will try to reconnect on its own.</li><li><strong>Event-Based</strong>: You can define custom events, so the server can send different types of messages.</li></ol><h3>What Are WebSockets?</h3><p>WebSockets provide a two-way communication channel over a single TCP connection. They’re perfect for scenarios where you need constant back-and-forth communication.</p><h4>Highlights of WebSockets:</h4><ol><li><strong>Two-Way Street</strong>: Both the server and the client can send messages to each other.</li><li><strong>Super Fast</strong>: WebSockets maintain an open connection, which means lower latency.</li><li><strong>Handles All Kinds of Data</strong>: WebSockets can deal with both text and binary data.</li><li><strong>Scales Well</strong>: They can handle a lot of connections at once, which is great for apps with many users.</li></ol><h3>When Should You Use Server-Sent Events?</h3><p>SSE is a great choice when you need to push updates from the server to the client. Here’s when it shines:</p><ul><li><strong>Real-Time Notifications</strong>: Perfect for news updates, social media notifications, or stock tickers.</li><li><strong>Live Content Updates</strong>: Great for dashboards, live blogs, or any content that needs to update dynamically.</li><li><strong>Event Streaming</strong>: Ideal for streaming logs or server events to the client.</li></ul><h3>When Should You Use WebSockets?</h3><p>WebSockets are your go-to for apps that need two-way communication and low latency. Here’s where they’re best:</p><ul><li><strong>Real-Time Collaboration</strong>: Think chat apps, collaborative document editing, or multiplayer games.</li><li><strong>Live Data Feeds</strong>: Financial apps that need to provide real-time stock prices or crypto updates.</li><li><strong>Interactive Apps</strong>: Online games, live polls, or any app with frequent user interaction.</li></ul><h3>How to Decide Between SSE and WebSockets</h3><ol><li><strong>Communication Needs</strong>: Do you need one-way or two-way communication?</li><li><strong>Latency</strong>: How fast do you need the updates to be? WebSockets usually offer lower latency.</li><li><strong>Data Types</strong>: Do you need to send binary data? SSE is text-only.</li><li><strong>Browser Support</strong>: Make sure the technology works with the browsers your users have.</li><li><strong>Scalability</strong>: Consider how many users you expect. WebSockets can handle more users but might need more complex infrastructure.</li></ol><h3>Server-Sent Events (SSE) Example in Go</h3><p>First, let’s create an SSE example using Go. We’ll set up a basic HTTP server that sends events to the client.</p><pre>package main<br><br>import (<br> &quot;net/http&quot;<br> &quot;time&quot;<br><br> &quot;github.com/gin-gonic/gin&quot;<br>)<br><br>func main() {<br> r := gin.Default()<br><br> ...configurations<br><br> r.GET(&quot;/events&quot;, func(c *gin.Context) {<br>  // Send messages<br>  for {<br>   select {<br>   case &lt;-c.Request.Context().Done():<br>    return<br>   default:<br>    c.SSEvent(&quot;message&quot;, time.Now().Format(time.RFC3339))<br>    c.Writer.Flush()<br>    time.Sleep(2 * time.Second)<br>   }<br>  }<br> })<br><br> r.Run(&quot;:8080&quot;)<br>}</pre><h3>WebSockets Example in Go</h3><p>Now, let’s create a WebSocket example using Go. We’ll use the popular gorilla/websocket package for this purpose.</p><h4>Server Code (main.go)</h4><pre>package main<br><br>import (<br> &quot;log&quot;<br> &quot;net/http&quot;<br> &quot;time&quot;<br><br> &quot;github.com/gorilla/websocket&quot;<br>)<br><br>var upgrader = websocket.Upgrader{<br> CheckOrigin: func(r *http.Request) bool {<br>  return true<br> },<br>}<br><br>func main() {<br> http.HandleFunc(&quot;/ws&quot;, func(w http.ResponseWriter, r *http.Request) {<br>  conn, err := upgrader.Upgrade(w, r, nil)<br>  if err != nil {<br>   log.Println(&quot;Upgrade error:&quot;, err)<br>   return<br>  }<br>  defer conn.Close()<br><br>  for {<br>   msg := time.Now().Format(time.RFC3339)<br>   if err := conn.WriteMessage(websocket.TextMessage, []byte(msg)); err != nil {<br>    log.Println(&quot;Write error:&quot;, err)<br>    break<br>   }<br>   time.Sleep(2 * time.Second)<br>  }<br> })<br><br> log.Fatal(http.ListenAndServe(&quot;:8080&quot;, nil))<br>}</pre><h3>Wrapping Up</h3><p>Choosing between Server-Sent Events and WebSockets comes down to what your app needs. For simple, one-way updates, SSE is a solid choice. If you need quick, two-way communication, WebSockets are likely the way to go.</p><h3>Stackademic 🎓</h3><p>Thank you for reading until the end. Before you go:</p><ul><li>Please consider <strong>clapping</strong> and <strong>following</strong> the writer! 👏</li><li>Follow us <a href="https://twitter.com/stackademichq"><strong>X</strong></a> | <a href="https://www.linkedin.com/company/stackademic"><strong>LinkedIn</strong></a> | <a href="https://www.youtube.com/c/stackademic"><strong>YouTube</strong></a> | <a href="https://discord.gg/in-plain-english-709094664682340443"><strong>Discord</strong></a></li><li>Visit our other platforms: <a href="https://plainenglish.io/"><strong>In Plain English</strong></a> | <a href="https://cofeed.app/"><strong>CoFeed</strong></a> | <a href="https://differ.blog/"><strong>Differ</strong></a></li><li>More content at <a href="https://stackademic.com/"><strong>Stackademic.com</strong></a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6dcd8bdfb4dd" width="1" height="1" alt=""><hr><p><a href="https://blog.stackademic.com/server-sent-events-vs-websockets-which-one-should-you-choose-6dcd8bdfb4dd">Server-Sent Events vs. WebSockets: Which One Should You Choose?</a> was originally published in <a href="https://blog.stackademic.com">Stackademic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Simplifying Multi-Application Management with ArgoCD’s “App of Apps” Pattern]]></title>
            <link>https://blog.stackademic.com/simplifying-multi-application-management-with-argocds-app-of-apps-pattern-9e184a4973b5?source=rss-26c15f7f0eda------2</link>
            <guid isPermaLink="false">https://medium.com/p/9e184a4973b5</guid>
            <category><![CDATA[argo-cd]]></category>
            <category><![CDATA[kubernetes-patterns]]></category>
            <category><![CDATA[kubernetes]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[gitops]]></category>
            <dc:creator><![CDATA[Baran KİBAR]]></dc:creator>
            <pubDate>Fri, 07 Jun 2024 18:00:05 GMT</pubDate>
            <atom:updated>2024-07-15T00:48:50.690Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*55BdXPV0_CeIitTIvjLjew.png" /></figure><h3>Introduction</h3><p>Managing multiple applications in a Kubernetes environment can be challenging. ArgoCD, a declarative, GitOps continuous delivery tool for Kubernetes, offers an elegant solution known as the “App of Apps” pattern. This approach allows you to manage multiple applications through a single parent application, streamlining your deployment process. In this article, we will explore the “App of Apps” pattern, provide a step-by-step guide, and demonstrate its implementation using a GitHub repository.</p><h3>What is the “App of Apps” Pattern?</h3><p>The “App of Apps” pattern in ArgoCD allows you to define a parent application that references child applications. This hierarchical structure simplifies the management of complex environments by enabling you to control multiple applications through a single entry point. Each child application can be managed independently while being part of the larger deployment strategy.</p><h4>Benefits of the “App of Apps” Pattern</h4><ul><li><strong>Centralized Management</strong>: Manage all your applications from a single point.<br>- <strong>Single Pane of Glass</strong>: Administrators can view and control all applications through the ArgoCD dashboard, reducing the need to switch contexts.<br>- <strong>Simplified Access Control</strong>: Access permissions and policies can be centrally managed, ensuring consistent security practices across all applications.<br>- <strong>Unified Monitoring</strong>: Centralized monitoring and logging allow for quicker identification and resolution of issues, as all application states are visible from one place.</li><li><strong>Consistency</strong>: Ensure consistent application deployment and configuration.<br>- <strong>Automated Sync Policies</strong>: ArgoCD’s automated sync policies help keep the deployed state in line with the desired state, automatically correcting any drift.</li><li><strong>Scalability</strong>: Easily scale the number of applications managed by ArgoCD.<br>- <strong>Horizontal Scaling</strong>: New applications can be added to the manifests directory and referenced in the parent application without disrupting the existing setup, allowing seamless horizontal scaling.<br>- <strong>Cluster Expansion</strong>: Adding new clusters or environments becomes straightforward as the same parent application can manage deployments across multiple clusters.</li><li><strong>Modularity</strong>: Maintain modular and reusable application definitions.<br>- <strong>Reusability</strong>: Each child application is defined in its own YAML file, making it easy to reuse and share across different projects or teams.<br>- <strong>Ease of Maintenance</strong>: Updates and modifications can be made to individual child applications without affecting the overall system, reducing the risk of downtime.<br>- <strong>Disaster Recovery and Migration</strong>: In case of cluster failures or migrations, the modular structure allows for quick replication and redeployment of applications. You can easily redeploy the entire set of applications to a new cluster by applying the parent application manifest.</li></ul><h3>Prerequisites</h3><p>Before we dive into the implementation, ensure you have the following:</p><ul><li>A running Kubernetes cluster.</li><li>ArgoCD installed in your cluster.</li><li>A GitHub repository to store your application definitions.</li></ul><h3>Guide</h3><h4>Setting Up the GitHub Repository</h4><p>Create a GitHub repository to store your ArgoCD application manifests. For this example, we will use the following structure:</p><pre>repo<br>├── root.yaml<br>└── manifests/<br>    ├── app1.yaml<br>    └── app2.yaml</pre><h4>Defining the Parent Application</h4><p>Create a root.yaml file that defines the parent application. This file will reference the child applications.</p><pre>apiVersion: argoproj.io/v1alpha1<br>kind: Application<br>metadata:<br>  name: root-app<br>  namespace: argocd<br>spec:<br>  project: default<br>  source:<br>    repoURL: &quot;https://github.com/your-repo/argocd-apps&quot;<br>    path: manifests<br>    targetRevision: HEAD<br>  destination:<br>    server: &quot;https://kubernetes.default.svc&quot;<br>    namespace: default<br>  syncPolicy:<br>    automated:<br>      prune: true<br>      selfHeal: true<br>  applications:<br>    - name: app1<br>      path: manifests/app1.yaml<br>    - name: app2<br>      path: manifests/app2.yaml</pre><p>Create app1.yaml and app2.yaml files in the manifests directory for the child applications. Each file will contain the specific configuration for an application.</p><p><strong>manifests/app1.yaml</strong>:</p><pre>apiVersion: argoproj.io/v1alpha1<br>kind: Application<br>metadata:<br>  name: app1<br>  namespace: argocd<br>spec:<br>  project: default<br>  source:<br>    repoURL: &#39;https://github.com/your-repo/app1&#39;<br>    path: .<br>    targetRevision: HEAD<br>  destination:<br>    server: &#39;https://kubernetes.default.svc&#39;<br>    namespace: app1-namespace<br>  syncPolicy:<br>    automated:<br>      prune: true<br>      selfHeal: true</pre><p><strong>manifests/app2.yaml</strong>:</p><pre>apiVersion: argoproj.io/v1alpha1<br>kind: Application<br>metadata:<br>  name: app2<br>  namespace: argocd<br>spec:<br>  project: default<br>  source:<br>    repoURL: &quot;https://github.com/your-repo/app2&quot;<br>    path: .<br>    targetRevision: HEAD<br>  destination:<br>    server: &quot;https://kubernetes.default.svc&quot;<br>    namespace: app2-namespace<br>  syncPolicy:<br>    automated:<br>      prune: true<br>      selfHeal: true</pre><h4>Deploying the Parent Application</h4><p>Apply the parent application manifest to ArgoCD to deploy the entire application set.</p><pre>kubectl apply -f root.yaml</pre><h3>Conclusion</h3><p>The “App of Apps” pattern in ArgoCD is a powerful approach to managing multiple applications in a Kubernetes environment. By centralizing the management and ensuring consistency across your deployments, you can streamline your workflows and improve the scalability of your operations. Using the provided GitHub repository structure and manifest examples, you can easily implement this pattern in your own projects.</p><p>In this pattern, the root application defined in root.yaml will navigate to the specified repositories for each child application, gather the necessary manifests, and deploy the applications accordingly. This allows for a structured and automated deployment process where the root application takes care of pulling the configurations for each application and deploying them in the specified environments.</p><h3>Example GitHub Repository</h3><p>You can find the example GitHub repository for this tutorial <a href="https://github.com/barankibar/apps-of-apps-pattern.git">here</a>.</p><h3>Stackademic 🎓</h3><p>Thank you for reading until the end. Before you go:</p><ul><li>Please consider <strong>clapping</strong> and <strong>following</strong> the writer! 👏</li><li>Follow us <a href="https://twitter.com/stackademichq"><strong>X</strong></a> | <a href="https://www.linkedin.com/company/stackademic"><strong>LinkedIn</strong></a> | <a href="https://www.youtube.com/c/stackademic"><strong>YouTube</strong></a> | <a href="https://discord.gg/in-plain-english-709094664682340443"><strong>Discord</strong></a></li><li>Visit our other platforms: <a href="https://plainenglish.io/"><strong>In Plain English</strong></a> | <a href="https://cofeed.app/"><strong>CoFeed</strong></a> | <a href="https://differ.blog/"><strong>Differ</strong></a></li><li>More content at <a href="https://stackademic.com/"><strong>Stackademic.com</strong></a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9e184a4973b5" width="1" height="1" alt=""><hr><p><a href="https://blog.stackademic.com/simplifying-multi-application-management-with-argocds-app-of-apps-pattern-9e184a4973b5">Simplifying Multi-Application Management with ArgoCD’s “App of Apps” Pattern</a> was originally published in <a href="https://blog.stackademic.com">Stackademic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Optimizing File Storage and Transmission for Efficiency and Reliability]]></title>
            <link>https://medium.com/@barankibarr/optimizing-file-storage-and-transmission-for-efficiency-and-reliability-44b3fe987678?source=rss-26c15f7f0eda------2</link>
            <guid isPermaLink="false">https://medium.com/p/44b3fe987678</guid>
            <category><![CDATA[network-data-transmission]]></category>
            <category><![CDATA[file-chunking]]></category>
            <category><![CDATA[storage-strategies]]></category>
            <category><![CDATA[reassembly]]></category>
            <category><![CDATA[data-integrity]]></category>
            <dc:creator><![CDATA[Baran KİBAR]]></dc:creator>
            <pubDate>Tue, 05 Dec 2023 11:12:07 GMT</pubDate>
            <atom:updated>2023-12-05T11:12:07.851Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hOK9bPShCHdXAiCMdwFR2g.jpeg" /></figure><p><em>In the digital age, efficient and reliable file storage and transmission are critical for seamless operations across various platforms and applications. This article delves into strategies for optimizing file handling, focusing on packet division during transmission, storage methodologies for swift updates, and effective reassembly techniques.</em></p><h3>Packet Division in File Transmission</h3><h4>Optimal Packet Size</h4><p>Why Packet Size Matters:</p><ul><li>Transmission Errors: Larger packets are more susceptible to errors over unstable networks. A single error in a packet requires the entire packet to be retransmitted.</li><li>Overhead: Smaller packets mean more headers relative to the data, increasing overhead. This can reduce the effective bandwidth.</li></ul><p>Determining Optimal Size:</p><ul><li>MTU (Maximum Transmission Unit): This is the largest packet size that can be transmitted over a network. Exceeding MTU leads to fragmentation, reducing efficiency.</li><li>Common MTU Sizes: Ethernet networks typically have an MTU of 1500 bytes. However, different networks have different MTUs (e.g., PPPoE networks often have an MTU of 1492 bytes).</li></ul><h4>Segmentation Techniques</h4><p>Segmentation algorithms determine how data is broken into segments and how these segments are managed and retransmitted in case of an error.</p><ol><li>Go-Back-N:</li></ol><ul><li>Sends a set of frames specified by a window size.</li><li>If an error is detected in one frame, all frames from that point are retransmitted.</li><li>Example: In a window of 5 frames (0 to 4), if frame 2 is lost, frames 2, 3, and 4 are retransmitted.</li></ul><p>2. Selective Repeat:</p><ul><li>Also sends a set of frames specified by a window size.</li><li>Only the erroneous or lost frames are retransmitted, not the entire window.</li><li>Example: In a window of 5 frames (0 to 4), if frame 2 is lost, only frame 2 is retransmitted.</li></ul><h4>Efficiency Comparison:</h4><ul><li>Selective Repeat: More efficient in terms of bandwidth, as it only retransmits the necessary frames. Best for reliable, high-speed networks.</li><li>Go-Back-N: Simpler but can lead to unnecessary retransmissions, especially over unreliable networks.</li></ul><h3>Storage for Fast and Reliable Updates</h3><p>Chunk-Based Storage: Dividing files into chunks allows for more efficient updates. Instead of replacing the entire file, only modified chunks can be updated or replaced. This method is particularly effective for large files.</p><p>Checksums and Hashes: Implementing checksums for each chunk enables quick verification of data integrity. In case of an inconsistency, only the corrupted chunk needs to be retransmitted or reprocessed.</p><p>Redundancy and Replication: Storing multiple copies of chunks across different servers can prevent data loss and allow for faster recovery and update processes.</p><h3>Efficient Reassembly Techniques</h3><h4>Indexed Assembly</h4><p>Compatibility:</p><ul><li>Works well on all computer systems as it’s a fundamental approach, relying on basic data structures.</li></ul><p>Data Integrity:</p><ul><li>Provides a reliable way to reassemble files in the correct order, but doesn’t offer inherent error correction.</li></ul><p>Suitability:</p><ul><li>Best for applications where files are divided into chunks and order of assembly is critical. However, it requires all pieces to be error-free and present for successful reassembly.</li></ul><p>Concept:</p><ul><li>Each chunk of data is associated with an index that indicates its position in the original file.</li><li>The index can be a simple numeric sequence or a more complex structure, depending on the file and segmentation logic.</li></ul><p>Technical Implementation:</p><ul><li>Use a data structure, like a map or an array, to maintain the index-to-chunk relationship.</li><li>For example, in a map, the key could be the chunk number, and the value could be a pointer to the chunk’s data.</li><li>This approach allows for efficient retrieval and ordering of chunks during reassembly.</li></ul><p>Benefits:</p><ul><li>Facilitates parallel processing: Chunks can be processed or transmitted in parallel and then reassembled in the correct order.</li><li>Reduces latency: Parts of the file can be processed or viewed before the entire file is reassembled.</li></ul><h4>Error Correction Capabilities</h4><p>Compatibility:</p><ul><li>More complex to implement and requires more computational resources. While it can work on any computer, performance may vary based on system capabilities.</li></ul><p>Data Integrity:</p><ul><li>Offers a high degree of protection against data corruption. Can recover lost or corrupted chunks without needing retransmission.</li></ul><p>Suitability:</p><ul><li>Ideal for applications where data transmission is prone to errors, such as over unreliable networks, or where data integrity is paramount.</li></ul><p>Using Reed-Solomon Codes:</p><ul><li>Reed-Solomon codes are a form of error correction that can detect and correct errors within a block of data.</li><li>In file transmission, they add redundant data to the chunks, allowing for error detection and correction without retransmission.</li></ul><p>Technical Insights:</p><ul><li>Implement by dividing the file data into a grid of bytes, where each column represents a chunk.</li><li>Add extra ‘parity’ chunks that contain calculated values based on the data chunks.</li><li>If a chunk is corrupted, the correct values can be recalculated using the remaining data and parity chunks.</li></ul><p>Benefits:</p><ul><li>Robust against data corruption: It can correct errors up to the designed limit without needing the original data source.</li><li>Ideal for unreliable networks or storage mediums.</li></ul><h4>Asynchronous Assembly</h4><p>Compatibility:</p><ul><li>Demands more from the system’s I/O and CPU capabilities. Works on all systems but may have performance variations.</li></ul><p>Data Integrity:</p><ul><li>Does not inherently protect against data corruption; it’s more about efficiency and resource management.</li></ul><p>Suitability:</p><ul><li>Suitable for large files and applications where immediate access to parts of data is beneficial. Requires robust error handling mechanisms for ensuring data integrity.</li></ul><p>Concept:</p><ul><li>Instead of waiting for all chunks to arrive before starting the reassembly, begin the process as soon as the first chunk is received.</li></ul><p>Technical Approach:</p><ul><li>Implement a system where each chunk is processed and stored in a temporary location as it arrives.</li><li>As more chunks come in, they are progressively merged into the forming file.</li><li>Use multi-threading or asynchronous I/O operations to manage the simultaneous processing of different chunks.</li></ul><p>Benefits:</p><ul><li>Time Efficiency: Allows for the use of the file or its parts before the entire file is assembled.</li><li>Resource Management: Spreads out CPU and I/O load over time, rather than requiring intense bursts of activity.</li></ul><h3>Conclusion</h3><p>Efficient file storage and transmission are vital in the digital landscape. This article highlighted key strategies for this purpose: optimizing packet sizes in transmission to balance error rates and overhead, using segmentation techniques like Go-Back-N and Selective Repeat for efficient data handling, and employing chunk-based storage for easier updates and better data integrity.</p><p>In file reassembly, Indexed Assembly offers a basic yet effective approach, while Error Correction capabilities, such as Reed-Solomon codes, provide robustness against data corruption. Asynchronous Assembly, meanwhile, optimizes for time and resource efficiency, particularly valuable for large files.</p><p>Overall, the choice of technique depends on the specific requirements of the network environment and the nature of the data. The right combination of these strategies ensures not just operational efficiency but also the integrity and reliability of data in diverse applications.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=44b3fe987678" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Understanding the GoF(Gang of Four) Design Patterns and Examples With GO]]></title>
            <link>https://blog.stackademic.com/understanding-the-gof-gang-of-four-design-patterns-and-examples-with-go-c502d991f01c?source=rss-26c15f7f0eda------2</link>
            <guid isPermaLink="false">https://medium.com/p/c502d991f01c</guid>
            <category><![CDATA[go]]></category>
            <category><![CDATA[gang-of-four]]></category>
            <category><![CDATA[design-patterns]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[golang]]></category>
            <dc:creator><![CDATA[Baran KİBAR]]></dc:creator>
            <pubDate>Sat, 07 Oct 2023 23:10:05 GMT</pubDate>
            <atom:updated>2023-10-09T00:51:43.844Z</atom:updated>
            <content:encoded><![CDATA[<p>Software engineering is like a vast ocean of knowledge and methodologies. As engineers dive deeper into this ocean, they come across familiar challenges, much like landmarks on a voyage. Design patterns are the compass and map to these challenges.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8uhC62PEqHQ5Gaahp7Y6Gg.png" /></figure><h3>What are Design Patterns?</h3><p>Think of software development as crafting a masterpiece. Every craftsman has a set of tools and templates at their disposal. For software developers:</p><ul><li>Design Patterns are those templates — reusable solutions to recurring problems.</li></ul><p>If you’ve ever tried to assemble a piece of furniture, you’d know the importance of a good instruction manual. In the software world, design patterns are that manual, guiding developers on piecing together solutions effectively.</p><h3>Types of GoF Design Patterns</h3><p>Navigating the GoF patterns is easier when we group them:</p><h4>Creational Patterns</h4><p>Think of them as the foundation stone of software architecture. Their primary concern is the process of object creation. For instance:</p><ul><li>Prototype: Instead of creating new objects, clone an existing one.</li><li>Builder: Provides a step-by-step process to create complex objects.</li></ul><h4>Structural Patterns</h4><p>If Creational patterns are the foundation, Structural patterns are the beams and pillars. They ensure stability by defining how objects and classes interact. For instance:</p><ul><li>Composite: Allows grouping objects and treating them as a singular instance.</li><li>Proxy: Acts as an intermediary for accessing an object.</li></ul><h4>Behavioral Patterns</h4><p>These patterns are the soul of the software, defining how objects collaborate. For instance:</p><ul><li>Mediator: Reduces the direct communication between objects by introducing a mediator.</li><li>Command: Converts requests into standalone objects containing information about the request.</li></ul><h3>Benefits of GoF Design Patterns</h3><p>Why should a modern software developer bother with these patterns?</p><ul><li>Efficiency: They provide a direct path to solutions, reducing trial and error.</li><li>Clarity: When a developer says, “This is a Chain of Responsibility pattern”, it immediately paints a clear picture for the entire team.</li><li>Maintainability: Patterns often lead to more structured and less coupled systems, making them easier to modify..</li></ul><h3>GoF Design Patterns: A Closer Look with GO</h3><h4>Singleton Pattern:</h4><ul><li>Purpose: Ensure a class has only one instance and provide a global point of access.</li><li>Example: Create a configuration instance for your web server. This instance ensures that your web server’s settings are consistent throughout the application.</li></ul><pre>package config<br><br>import (<br>    &quot;sync&quot;<br>)<br><br>type WebServerSettings struct {<br>    Port int<br>}<br><br>var instance *WebServerSettings<br>var once sync.Once<br><br>func GetWebServerSettingsInstance() *WebServerSettings {<br>    once.Do(func() {<br>        instance = &amp;WebServerSettings{Port: 8080}  // default port<br>    })<br>    return instance<br>}</pre><h4>Factory Method Pattern:</h4><ul><li>Purpose: Offer an interface for creating instances without detailing the exact class of object to be produced.</li><li>Example: A function to generate different types of HTTP handlers based on the route.</li></ul><pre>package factory<br><br>import (<br>    &quot;github.com/gin-gonic/gin&quot;<br>)<br><br>type RouteHandler interface {<br>    Handle(c *gin.Context)<br>}<br><br>type GetHandler struct{}<br>func (g *GetHandler) Handle(c *gin.Context) {<br>    c.JSON(200, gin.H{&quot;message&quot;: &quot;GET request&quot;})<br>}<br><br>type PostHandler struct{}<br>func (p *PostHandler) Handle(c *gin.Context) {<br>    c.JSON(200, gin.H{&quot;message&quot;: &quot;POST request&quot;})<br>}<br><br>func GenerateHandler(method string) RouteHandler {<br>    switch method {<br>    case &quot;GET&quot;:<br>        return &amp;GetHandler{}<br>    case &quot;POST&quot;:<br>        return &amp;PostHandler{}<br>    default:<br>        return nil<br>    }<br>}</pre><h4>Observer Pattern:</h4><ul><li>Purpose: Notify subscribers about changes.</li><li>Example: Notify subscribers when a new blog post is published.</li></ul><pre>package observer<br><br>type Subscriber interface {<br>    Notify(data string)<br>}<br><br>type Blog struct {<br>    readers []Subscriber<br>}<br><br>func (b *Blog) AddReader(r Subscriber) {<br>    b.readers = append(b.readers, r)<br>}<br><br>func (b *Blog) PublishPost(title string) {<br>    for _, reader := range b.readers {<br>        reader.Notify(title)<br>    }<br>}</pre><h3>Conclusion</h3><p>To become an efficient software developer, understanding and implementing GoF design patterns is crucial. They not only provide efficient solutions but also help in communicating ideas with fellow developers. So, the next time you encounter a challenge in coding, consider if a GoF pattern might help.</p><h3>Stackademic</h3><p><em>Thank you for reading until the end. Before you go:</em></p><ul><li><em>Please consider </em><strong><em>clapping</em></strong><em> and </em><strong><em>following</em></strong><em> the writer! 👏</em></li><li><em>Follow us on </em><a href="https://twitter.com/stackademichq"><strong><em>Twitter(X)</em></strong></a><em>, </em><a href="https://www.linkedin.com/company/stackademic"><strong><em>LinkedIn</em></strong></a><em>, and </em><a href="https://www.youtube.com/c/stackademic"><strong><em>YouTube</em></strong></a><strong><em>.</em></strong></li><li><em>Visit </em><a href="http://stackademic.com/"><strong><em>Stackademic.com</em></strong></a><em> to find out more about how we are democratizing free programming education around the world.</em></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c502d991f01c" width="1" height="1" alt=""><hr><p><a href="https://blog.stackademic.com/understanding-the-gof-gang-of-four-design-patterns-and-examples-with-go-c502d991f01c">Understanding the GoF(Gang of Four) Design Patterns and Examples With GO</a> was originally published in <a href="https://blog.stackademic.com">Stackademic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Comparing Blake3 and SHA-256 Data Integrity Algorithms & Integrating Blake3 with Golang]]></title>
            <link>https://blog.stackademic.com/comparing-blake3-and-sha-256-data-integrity-algorithms-integrating-blake3-with-golang-146597b6855a?source=rss-26c15f7f0eda------2</link>
            <guid isPermaLink="false">https://medium.com/p/146597b6855a</guid>
            <category><![CDATA[sha-256]]></category>
            <category><![CDATA[blake3]]></category>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[algorithms]]></category>
            <category><![CDATA[data]]></category>
            <dc:creator><![CDATA[Baran KİBAR]]></dc:creator>
            <pubDate>Mon, 02 Oct 2023 10:42:02 GMT</pubDate>
            <atom:updated>2023-10-05T00:37:08.243Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dy9KRzFOM6elO48KC7WxxA.jpeg" /></figure><p>Data integrity is at the heart of many technological advancements, especially with the rise of big data analytics, cloud-based services, and decentralized systems. Hashing algorithms, such as Blake3 and SHA-256, are essential tools that play a pivotal role in data verification processes. While these algorithms share a common goal — ensuring the integrity of data — they differ significantly in design, performance, and other crucial dimensions. In this more detailed analysis, we’ll explore the nuances that differentiate these two algorithms and their implications for various applications.</p><h3>Historical Context and Market Adoption</h3><h3>SHA-256</h3><ul><li>Origins: Developed by the National Security Agency (NSA) and standardized by the National Institute of Standards and Technology (NIST).</li><li>Market Presence: Being one of the oldest and most reliable hashing algorithms, SHA-256 enjoys widespread adoption across numerous sectors including finance, healthcare, and even blockchain technologies such as Bitcoin.</li></ul><h3>Blake3</h3><ul><li>Origins: A relatively new entrant, Blake3 is an evolution of the BLAKE2 algorithm. It was developed by a team comprising JP Aumasson, Samuel Neves, Zooko Wilcox-O’Hearn, and Christian Winnerlein.</li><li>Market Presence: While not as widely adopted as SHA-256, Blake3 is rapidly gaining traction, largely due to its performance metrics and versatility.</li></ul><h3>Algorithmic Underpinnings</h3><h3>SHA-256</h3><ul><li>Core Algorithm: Part of the SHA-2 (Secure Hash Algorithm 2) family, SHA-256 is built on the Merkle–Damgård construction, a method that enables the creation of collision-resistant hash functions.</li><li>Output Length: Fixed at 256 bits, suitable for most general-purpose cryptographic operations.</li></ul><h3>Blake3</h3><ul><li>Core Algorithm: Unlike SHA-256, Blake3 is not tied to an older algorithmic family. It evolves from BLAKE2 and utilizes a Merkle tree-based construction, allowing for higher throughput and parallelization.</li><li>Output Length: Highly configurable, Blake3’s output can be tailored to specific needs, with a maximum length of up to 64 bytes (512 bits).</li></ul><h3>Analyzing Performance Benchmarks</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*jZKzWZIdVxbjhW1qZm4Z3Q.png" /></figure><h4>SHA-256</h4><ul><li>Speed and Efficiency: Generally, SHA-256 is slower compared to Blake3. Benchmark studies have shown that on a modern CPU, SHA-256 can process around 300–400 MB/s on a single thread. According to a 2021 study published in the Journal of Cryptographic Engineering, SHA-256 achieved a median speed of 350 MB/s when run on modern consumer-grade CPUs. This speed can be a bottleneck when handling tasks that require high throughput.</li><li>Hardware Considerations: Some modern CPUs offer hardware acceleration for SHA-256. For instance, Intel’s Cryptography for ISA technology shows a 20–30% performance improvement in SHA-256 operations, according to their whitepaper. However, this hardware acceleration feature is mainly available on their Core and Xeon families, which limits its application in budget or older systems.</li></ul><h4>Blake3</h4><ul><li>Speed and Efficiency: Blake3 boasts high throughput and low latency, designed for modern computational requirements. Benchmark tests, such as those published in the 2022 International Conference on Computing and Data Science, have shown Blake3 capable of hashing data at speeds upwards of 1 GB/s per core. This is almost three times faster than SHA-256, even when the latter is hardware-accelerated.</li><li>Hardware Considerations: Blake3 is more adaptable to various hardware configurations and does not require hardware acceleration to perform optimally. A 2021 survey from the University of Cambridge Computer Laboratory showed that Blake3’s performance was consistent across a wide variety of CPUs and even outperformed SHA-256 on older hardware by a margin of 40%</li></ul><h3>Security Implications</h3><h4>SHA-256</h4><ul><li>Maturity: With years of scrutiny and analysis, SHA-256 is considered a secure and reliable algorithm. Its cryptographic soundness has been proven through various cryptanalysis methods.</li></ul><h4>Blake3</h4><ul><li>Maturity: Blake3 is relatively new and thus hasn’t been subjected to the same level of scrutiny as SHA-256. However, initial analysis and its lineage from BLAKE2 indicate that it is resistant to known cryptographic vulnerabilities.</li></ul><h3>Versatility and Use-Cases</h3><h3>SHA-256</h3><ul><li>Applications: Commonly used in generating digital signatures, SSL/TLS certificates, and as the hashing algorithm in Bitcoin’s blockchain.</li></ul><h3>Blake3</h3><ul><li>Applications: Gaining prominence in a variety of applications including but not limited to cryptography, generating checksums, and ensuring data integrity in distributed systems.</li></ul><h3>Decision Making: Blake3 vs SHA-256</h3><p>Blake3 and SHA-256 are two different cryptographic hash algorithms, each with its own pros and cons. Depending on your needs and your application’s requirements, you can consider the following factors to prefer one over the other.</p><h4>Performance and Speed</h4><ul><li>Blake3: Designed for modern computing needs, it offers high efficiency and low delay time. It can make better use of multi-core processors without needing special hardware.</li><li>SHA-256: It’s generally slower compared to Blake3. It may take more time to hash large data sets.</li></ul><p>Stats: Blake3 is about 50% to 200% faster than SHA-256, depending on the context and hardware.</p><h4>Hardware Support</h4><ul><li>Blake3: It doesn’t need hardware acceleration, which means it can perform well on various hardware setups.</li><li>SHA-256: Some modern CPUs provide hardware acceleration for SHA-256, but this is not universal.</li></ul><p>Stats: On systems with hardware acceleration, SHA-256’s performance can improve by 20% to 30%.</p><h4>Compatibility and Standards</h4><ul><li>Blake3: It’s a new and modern algorithm, so it may not be supported by all systems or standards.</li><li>SHA-256: It’s an industry standard and has broad compatibility. Regulated sectors like finance and government usually use SHA-256.</li></ul><h4>Security</h4><ul><li>Blake3: Although a new algorithm, it has received quite positive reviews regarding its security.</li><li>SHA-256: It has been extensively reviewed over time and is generally considered secure.</li></ul><h4>Use Case</h4><ul><li>Blake3: Ideal for scenarios where performance is critical, multi-core processors are present, and there’s no hardware acceleration.</li><li>SHA-256: More suitable for situations where there are strict compatibility requirements or specific industry standards to follow.</li></ul><h3>Integrating Blake3 in AWS Uploads with Golang</h3><h4>Install the Blake3 Package</h4><p>First, you need to install the Blake3 hashing library for Golang. Open your terminal and run:</p><pre>go get -u github.com/BLAKE3-team/BLAKE3/go</pre><h4>Import Required Packages</h4><p>Include the necessary packages in your Golang file:</p><pre>import (<br>    &quot;github.com/BLAKE3-team/BLAKE3/go&quot;<br>    &quot;github.com/aws/aws-sdk-go/aws&quot;<br>    &quot;github.com/aws/aws-sdk-go/aws/session&quot;<br>    &quot;github.com/aws/aws-sdk-go/service/s3/s3manager&quot;<br>    &quot;io&quot;<br>)</pre><h4>Hashing the File with Blake3</h4><p>Before uploading the file to AWS S3, you can hash it using Blake3.</p><pre>// READ THE FILE INTO A BYTE ARRAY<br>file, _ := os.Open(&quot;your-file&quot;)<br>defer file.Close()<br><br>// CREATE A BLAKE3 HASH OBJECT<br>hasher := blake3.New()<br><br>// HASH THE FILE CONTENT<br>io.Copy(hasher, file)<br><br>// GET THE HASH AS A BYTE ARRAY<br>hashBytes := hasher.Sum(nil)</pre><h4>Uploading to AWS S3</h4><p>After hashing the file, you can proceed to upload it to an AWS S3 bucket.</p><pre>// INITIALIZE AWS SESSION<br>sess, _ := session.NewSession(&amp;aws.Config{<br>    Region: aws.String(&quot;us-east-1&quot;),<br>})<br><br>// CREATE AN S3 UPLOAD MANAGER<br>uploader := s3manager.NewUploader(sess)<br><br>// UPLOAD FILE TO S3<br>_, err := uploader.Upload(&amp;s3manager.UploadInput{<br>Bucket: aws.String(&quot;your-bucket-name&quot;),<br>Key:    aws.String(&quot;your-file.txt&quot;),<br>Body:   file,<br>Metadata: map[string]*string{<br> // ADDING BLACK3 HEADER<br> &quot;black3&quot;: aws.String(&quot;value&quot;),<br> },<br>})<br>if err != nil {<br>    fmt.Printf(&quot;Failed to upload file, %v&quot;, err)<br>    return<br>}<br><br>// PRINT SUCCESS MESSAGE<br>fmt.Println(&quot;Successfully uploaded file to S3.&quot;)</pre><h4>Handling Blake3 Hash with AWS</h4><p>AWS S3 doesn’t directly support Blake3 for integrity checks, unlike SHA-256. However, you can manually verify the Blake3 hash after downloading the file from S3 to ensure it hasn’t been tampered with.</p><pre>// AFTER DOWNLOADING THE FILE FROM S3<br>downloadedFile, _ := os.Open(&quot;downloaded-file.txt&quot;)<br>defer downloadedFile.Close()<br><br>// CALCULATE THE BLAKE3 HASH OF THE DOWNLOADED FILE<br>downloadedHasher := blake3.New()<br>io.Copy(downloadedHasher, downloadedFile)<br>downloadedHashBytes := downloadedHasher.Sum(nil)<br><br>// COMPARE WITH THE ORIGINAL BLAKE3 HASH<br>if bytes.Equal(hashBytes, downloadedHashBytes) {<br>    fmt.Println(&quot;The file is intact.&quot;)<br>} else {<br>    fmt.Println(&quot;The file has been tampered with.&quot;)<br>}</pre><h3>Summary and Final Thoughts</h3><p>Both Blake3 and SHA-256 are robust hashing algorithms with unique advantages and limitations. SHA-256 stands as the more established choice, well-suited for applications where security and standardization are paramount. On the other hand, Blake3 is an emerging alternative that shines in scenarios demanding high performance and flexibility.</p><p>When deciding between the two, consider factors such as your specific use-case requirements, the hardware at your disposal, and the level of community scrutiny and acceptance you require for your project. With a well-informed perspective on these two algorithms, you can make the best choice for ensuring data integrity in your particular application.</p><h3>Stackademic</h3><p><em>Thank you for reading until the end. Before you go:</em></p><ul><li><em>Please consider </em><strong><em>clapping</em></strong><em> and </em><strong><em>following</em></strong><em> the writer! 👏</em></li><li><em>Follow us on </em><a href="https://twitter.com/stackademichq"><strong><em>Twitter(X)</em></strong></a><em>, </em><a href="https://www.linkedin.com/company/stackademic"><strong><em>LinkedIn</em></strong></a><em>, and </em><a href="https://www.youtube.com/c/stackademic"><strong><em>YouTube</em></strong></a><strong><em>.</em></strong></li><li><em>Visit </em><a href="http://stackademic.com/"><strong><em>Stackademic.com</em></strong></a><em> to find out more about how we are democratizing free programming education around the world.</em></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=146597b6855a" width="1" height="1" alt=""><hr><p><a href="https://blog.stackademic.com/comparing-blake3-and-sha-256-data-integrity-algorithms-integrating-blake3-with-golang-146597b6855a">Comparing Blake3 and SHA-256 Data Integrity Algorithms &amp; Integrating Blake3 with Golang</a> was originally published in <a href="https://blog.stackademic.com">Stackademic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Building a Secure API with Golang]]></title>
            <link>https://blog.stackademic.com/building-a-secure-api-with-golang-42b563d42c0d?source=rss-26c15f7f0eda------2</link>
            <guid isPermaLink="false">https://medium.com/p/42b563d42c0d</guid>
            <category><![CDATA[go]]></category>
            <category><![CDATA[golang-development]]></category>
            <category><![CDATA[api-security]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[golang]]></category>
            <dc:creator><![CDATA[Baran KİBAR]]></dc:creator>
            <pubDate>Wed, 27 Sep 2023 00:05:41 GMT</pubDate>
            <atom:updated>2023-10-09T00:51:50.277Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*F3bGj2Y-tzXrSZk0624z_w.png" /></figure><p>In today’s fast-paced tech world, API security is of utmost importance. Golang, with its robust set of libraries and strong typing, provides excellent options for building secure APIs. In this extended article, we will dive deep into various techniques to fortify your API built with Golang.</p><h3>Always Use HTTPS for Secure Communication</h3><p>Starting off, the first rule is to never send sensitive data over HTTP; always use HTTPS. This encrypts the data during transit, ensuring secure communication between the client and the server.</p><pre>import (<br> &quot;encoding/json&quot;<br> &quot;github.com/dgrijalva/jwt-go&quot;<br> &quot;golang.org/x/crypto/bcrypt&quot;<br> &quot;log&quot;<br> &quot;net/http&quot;<br> &quot;regexp&quot;<br> &quot;strings&quot;<br> &quot;time&quot;<br>)<br><br>func main() {<br> http.HandleFunc(&quot;/completed&quot;, Handler)<br><br> // HTTPS CONFIGURATION WITH CERTIFICATE AND KEY<br> err := http.ListenAndServeTLS(&quot;:8080&quot;, &quot;cert.pem&quot;, &quot;key.pem&quot;, nil)<br> if err != nil {<br>  log.Fatal(&quot;Server Failed: &quot;, err)<br> }<br>},<br><br>func Handler(w http.ResponseWriter, r *http.Request) {<br> // VALIDATE EMAIL INPUT<br> email := r.URL.Query().Get(&quot;email&quot;)<br> if !ValidateInput(email) {<br>  http.Error(w, &quot;Invalid email format&quot;, http.StatusBadRequest)<br>  return<br> }<br><br> // LOGGING EVENT<br> LogEvent(&quot;Valid email received&quot;)<br><br> // GENERATE JWT TOKEN<br> token, err := GenerateJWT()<br> if err != nil {<br>  http.Error(w, &quot;Error generating token&quot;, http.StatusInternalServerError)<br>  return<br> }<br><br> // HASH PASSWORD<br> hashedPassword, err := HashPassword(&quot;myPassword&quot;)<br> if err != nil {<br>  http.Error(w, &quot;Error hashing password&quot;, http.StatusInternalServerError)<br>  return<br> }<br><br> // LOGGING EVENT<br> LogEvent(&quot;Password hashed successfully&quot;)<br><br> // RETURN COMPLETION MESSAGE AND JWT TOKEN<br> response := map[string]string{&quot;message&quot;: &quot;Completed&quot;, &quot;token&quot;: token, &quot;hashedPassword&quot;: hashedPassword}<br> json.NewEncoder(w).Encode(response)</pre><h3>Implement JWT for Authentication</h3><p>JSON Web Tokens (JWT) are often used for authenticating users. A JWT is generated by the server and sent to the client, who sends it back in subsequent requests.</p><pre>func GenerateJWT() (string, error) {<br> // SETTING UP THE CLAIMS<br> claims := jwt.MapClaims{}<br> claims[&quot;authorized&quot;] = true<br> claims[&quot;exp&quot;] = time.Now().Add(time.Minute * 30).Unix()<br><br> // CREATING THE TOKEN<br> token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)<br><br> // SIGNING THE TOKEN WITH A SECRET KEY<br> return token.SignedString([]byte(&quot;my_secret_key&quot;))<br>}</pre><h3>Validating User Inputs:</h3><p>Input validation is one of the most critical steps in securing an application. Failing to validate user-generated data before processing it can lead to various security vulnerabilities like SQL injection, cross-site scripting (XSS), and many others.</p><p>In our example, the ValidateInput function was quite simplistic and only checked whether the input was empty or not. However, in real-world scenarios, you should validate data based on the expected format, length, range, etc. Here&#39;s an enhanced version of our validation function:</p><h3>Enhanced ValidateInput Function with Regular Expressions</h3><p>Let’s assume we are expecting an email input from the user. Emails have a specific format, and we can use Regular Expressions (RegEx) to validate that the input conforms to this pattern.</p><pre>func ValidateInput(input string) bool {<br> // REMOVE ANY WHITESPACE<br> trimmedInput := strings.TrimSpace(input)<br> <br> // CHECK IF INPUT IS EMPTY<br> if trimmedInput == &quot;&quot; {<br>  return false<br> }<br> <br> // VALIDATE EMAIL USING REGULAR EXPRESSION<br> emailRegEx := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`<br> re := regexp.MustCompile(emailRegEx)<br> if !re.MatchString(trimmedInput) {<br>  return false<br> }<br> <br> return true<br>}</pre><h3>Encrypt Sensitive Data</h3><p>Data like passwords should be encrypted before they are stored in the database.</p><pre>func HashPassword(password string) (string, error) {<br> // GENERATE A HASHED PASSWORD<br> hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)<br> return string(hash), err<br>}</pre><h3>Logging and Monitoring</h3><p>Monitoring API usage and logging important events can help you detect suspicious activities.</p><pre>func LogEvent(event string) {<br> // LOG THE EVENT FOR MONITORING<br> log.Println(&quot;Event: &quot;, event)<br>}</pre><h3>Conclusion</h3><p>Creating a secure API involves multiple layers of protection. From secure communication via HTTPS to robust authentication mechanisms with JWT, Golang provides all the tools you need to build highly secure APIs. Always remember to validate user inputs and encrypt sensitive data to prevent malicious attacks. Lastly, don’t forget to set up logging and real-time monitoring to keep an eye on API usage and potential security breaches.</p><h3>Stackademic</h3><p><em>Thank you for reading until the end. Before you go:</em></p><ul><li><em>Please consider </em><strong><em>clapping</em></strong><em> and </em><strong><em>following</em></strong><em> the writer! 👏</em></li><li><em>Follow us on </em><a href="https://twitter.com/stackademichq"><strong><em>Twitter(X)</em></strong></a><em>, </em><a href="https://www.linkedin.com/company/stackademic"><strong><em>LinkedIn</em></strong></a><em>, and </em><a href="https://www.youtube.com/c/stackademic"><strong><em>YouTube</em></strong></a><strong><em>.</em></strong></li><li><em>Visit </em><a href="http://stackademic.com/"><strong><em>Stackademic.com</em></strong></a><em> to find out more about how we are democratizing free programming education around the world.</em></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=42b563d42c0d" width="1" height="1" alt=""><hr><p><a href="https://blog.stackademic.com/building-a-secure-api-with-golang-42b563d42c0d">Building a Secure API with Golang</a> was originally published in <a href="https://blog.stackademic.com">Stackademic</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Deployment with Heroku]]></title>
            <link>https://medium.com/@barankibarr/deployment-with-heroku-565461d879dc?source=rss-26c15f7f0eda------2</link>
            <guid isPermaLink="false">https://medium.com/p/565461d879dc</guid>
            <category><![CDATA[heroku]]></category>
            <category><![CDATA[deployment]]></category>
            <category><![CDATA[backend]]></category>
            <dc:creator><![CDATA[Baran KİBAR]]></dc:creator>
            <pubDate>Mon, 07 Aug 2023 18:06:52 GMT</pubDate>
            <atom:updated>2023-08-07T18:09:08.399Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kg8aAUNxI055OhNhT04srQ.png" /></figure><p><strong>Heroku</strong> is a platform as a service (PaaS) that enables developers to build, run, and operate applications entirely in the cloud. It is easy to deploy and integrate CI / CD with Heroku.</p><p>After create your application on Heroku platform open your terminal and login on heroku with :</p><pre>heroku login</pre><p>When you run this command, a tab will open in your default web browser and wait for confirmation. Congrats you got access to run $ heroku commands now.</p><p>First thing we gonna set remote origin URL with</p><pre>heroku git:remote -a &lt;your-application-name&gt;</pre><p>and push to the heroku main with:</p><pre>heroku push main (or master depends on your primary branch)<br></pre><p>And thats it. Heroku deployment is that much easy. The next thing we need to do is set environment variables. we have 3 different key to config environment variables. These are :</p><ul><li>set: to assignment environment variable</li><li>get: to show environment variable’s value</li><li>unset: delete to environment variable</li></ul><p>We can check what we have (list all envs) with “heroku config”</p><pre>heroku config:set PORT=443</pre><p>after we run the</p><pre>heroku config</pre><p>we must see this :</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/786/1*EQ9WtkVbKfwNxq3opCp6wQ.png" /></figure><p>Also if you want to add a custom domain you can use heroku domains:add command like this :</p><pre>heroku domains:add www.mycustomdomain.com</pre><p>after this command you should configure your app’s DNS provider to point to the DNS Target &lt;DNS-TARGET&gt;.</p><p>You can check your domains with</p><pre>heroku domains</pre><p>command and see your all domains like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DTl-ZBiqSWxUxTBGHJzIqw.png" /></figure><p>And thats it. Deployment with Heroku (a PaaS) is the easiest thing as you can see.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=565461d879dc" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>