Category Archives: tech

technology

boto3 – discover ec2 internal IPs

🔐 Programmatically Discovering RHEL Ansible Node IPs in AWS (Boto3)


support@whitefeathers.org

In automated RHEL + Ansible environments on AWS, hardcoding host IPs doesn’t scale.
This small utility queries EC2 and prints private IP addresses for instances matching a naming
convention (ansible-rhel*) inside a specific VPC.

🧠 What this script does

  • Connects to EC2 in us-east-1
  • Filters by VPC ID and Name tag pattern ansible-rhel*
  • Limits results to instances in the running state
  • Returns/prints one private IP per line (ideal for inventory pipelines)

⚙️ Filters used

  • Region: us-east-1
  • VPC: vpc-0fc278c7fb8ffdbee (note: your comment references vpc-03ac09e77d044aabc)
  • Name tag: ansible-rhel*
  • State: running

Tip: If you meant the VPC in the header comment, update the filter to match it.

🧩 Source Code


# This function retrieves all internal IP addresses of RHEL Ansible nodes
# located in the 'us-east-1' region within the VPC 'vpc-03ac09e77d044aabc'.
# It returns a list of IP addresses, each on a new line, for instances
# whose names start with 'ansible-rhel*'.
# support@whitefeathers.org

import boto3  # Corrected import statement

def get_rhel_ansible_node_ips():
    """
    Retrieve the private IP addresses of running RHEL instances in a specified VPC.

    This function uses the Boto3 library to interact with the AWS EC2 service. It filters instances
    based on the provided VPC ID and a tag that matches 'ansible-rhel*'. The function returns a list
    of private IP addresses for all instances that are currently in the 'running' state.

    Returns:
        list: A list of private IP addresses of the matching EC2 instances.
    """
    ec2 = boto3.client('ec2', region_name='us-east-1')
    response = ec2.describe_instances(
        Filters=[
            {'Name': 'vpc-id', 'Values': ['vpc-0fc278c7fb8ffdbee']},
            {'Name': 'tag:Name', 'Values': ['ansible-rhel*']},
            {'Name': 'instance-state-name', 'Values': ['running']}
        ]
    )

    ip_addresses = []
    for reservation in response['Reservations']:
        for instance in reservation['Instances']:
            ip_addresses.append(instance['PrivateIpAddress'])

    return ip_addresses

def main():
    ip_addresses = get_rhel_ansible_node_ips()
    for ip in ip_addresses:
        print(ip)

if __name__ == "__main__":
    main()

📤 Example Output


10.20.4.17
10.20.4.23
10.20.5.11

🔄 Common extensions

  • Emit JSON for a dynamic Ansible inventory
  • Add additional filters (AMI, AZ, instance type)
  • Assume-role support for cross-account discovery
  • Pipe into post-patch validation workflows

© WhiteFeathers.org — automation patterns for AWS, RHEL, and Ansible.

AWS CLI — spot & on-demand ec2 prices

determine the price of spot t4g.large in us-east-1

$ aws ec2 describe-spot-price-history \
--region us-east-1 \
--instance-types t4g.large \
--product-descriptions "Linux/UNIX" \
--start-time "$(date -u -d '2 hours ago' +%FT%TZ)" \
--max-items 20 \
--query "SpotPriceHistory[].[AvailabilityZone,SpotPrice,Timestamp]" \
--output table
---------------------------------------------------------
| DescribeSpotPriceHistory |
+-------------+-----------+-----------------------------+
| us-east-1b | 0.028200 | 2026-01-30T20:02:43+00:00 |
| us-east-1c | 0.029800 | 2026-01-30T19:17:41+00:00 |
| us-east-1d | 0.031500 | 2026-01-30T19:17:41+00:00 |
| us-east-1a | 0.029500 | 2026-01-30T15:47:42+00:00 |
| us-east-1b | 0.028100 | 2026-01-30T15:34:11+00:00 |
| us-east-1d | 0.031700 | 2026-01-30T11:35:15+00:00 |
| us-east-1f | 0.033000 | 2026-01-30T09:47:55+00:00 |
| us-east-1c | 0.029900 | 2026-01-30T00:02:41+00:00 |
+-------------+-----------+-----------------------------+

determining the price of on-demand for the same

$ aws pricing get-products \
--region us-east-1 \
--service-code AmazonEC2 \
--filters \
Type=TERM_MATCH,Field=instanceType,Value=t4g.large \
Type=TERM_MATCH,Field=location,Value="US East (N. Virginia)" \
Type=TERM_MATCH,Field=operatingSystem,Value=Linux \
Type=TERM_MATCH,Field=tenancy,Value=Shared \
Type=TERM_MATCH,Field=preInstalledSw,Value=NA \
Type=TERM_MATCH,Field=capacitystatus,Value=Used \
--max-results 1 \
--output json \
| jq -r '
.PriceList[0] | fromjson
| .terms.OnDemand
| to_entries[0].value.priceDimensions
| to_entries[0].value.pricePerUnit.USD
'
0.0672000000

changing php default upload filesize

📤 Increase PHP File Upload Size in WordPress (Apache2)

By default, WordPress running on Apache + PHP limits file uploads to 2 MB.
That’s fine for icons—but not for high-quality images, videos, or modern content workflows.

Let’s fix that. 🚀


⚙️ The Solution

You can increase the upload limit directly from your .htaccess file.

📍 Location:
Your WordPress root directory (same level as wp-config.php)


✏️ Update .htaccess

Append the following lines to the bottom of the file:

php_value upload_max_filesize 64M
php_value post_max_size 64M
—–

🔍 What These Settings Do

  • upload_max_filesize → Maximum size of a single uploaded file 📦

  • post_max_size → Maximum total size of all POST data (must be ≥ upload size) 🧮

Both values should always match or post_max_size should be higher.


✅ Final Result

✔ Upload larger media files
✔ Fewer WordPress upload errors
✔ Better support for high-quality content 🎥📸


⚠️ Notes & Gotchas

  • This works only if PHP is running as an Apache module

  • If you’re using PHP-FPM, these values must be set in:

    • php.ini

    • or your pool config

  • Some hosts override .htaccess settings—check with your provider if changes don’t apply

 

run debug pod

Here are a few solid ways to spin up a debug pod in EKS (pick the one that matches what you’re troubleshooting).

1) Quick interactive “Swiss-army” debug pod (recommended)

This gives you an ephemeral pod you can exec into and run tools like curl, dig, nslookup, etc.

# Most clusters:

kubectl run -it --rm debug \
--image=nicolaka/netshoot \
--restart=Never \
--command -- bash
Inside the pod you can do stuff like:
ip a
curl -v https://kubernetes.default.svc
dig myservice.myns.svc.cluster.local

If your cluster blocks internet pulls, use an image from your own ECR.

2) Debug pod in a specific namespace + service account

Useful when you need the same IAM/RBAC/namespace behavior as an app.

NAMESPACE=weed
SA=smoker-sakubectl -n "$NAMESPACE" run -it --rm debug \
--image=nicolaka/netshoot \
--restart=Never \
--serviceaccount="$SA" \
--command -- bash

3) Debug from the same node (hostNetwork) to check node/DNS/routing

This makes the pod share the node network namespace (handy for “is the node routing/DNS broken?”).

kubectl run -it --rm debug-hostnet \
--image=nicolaka/netshoot \
--restart=Never \
--overrides='{
"spec": { "hostNetwork": true, "dnsPolicy": "ClusterFirstWithHostNet" }
}'
\
--command -- bash

4) Debug an existing pod with kubectl debug (ephemeral container)

Best when you want to debug without restarting the target pod.

kubectl debug -it pod/<pod-name> -n <ns> \
--image=nicolaka/netshoot \
--target=<container-name> \
-- bash

Notes:

  • Requires ephemeral containers enabled on the cluster (most modern EKS versions support it).

  • --target is the container whose namespaces you want to join.

5) Minimal YAML you can apply (if you prefer manifests)

apiVersion: v1
kind: Pod
metadata:
name: debug
namespace: default
spec:
restartPolicy: Never
containers:
- name: netshoot
image: nicolaka/netshoot
command: ["bash","-lc","sleep infinity"]

Apply + exec:

kubectl apply -f debug.yaml
kubectl exec -it debug -- bash

Common EKS debug checks (copy/paste)

# DNS
cat /etc/resolv.conf
nslookup kubernetes.default.svc.cluster.local
dig +short myservice.myns.svc.cluster.local
# Service connectivity
curl -vk https://<service-name>.<ns>.svc.cluster.local:<port># Network routes
ip route